On Thursday, 30 October 2014 at 12:51:50 UTC, Jonathan Marler
wrote:
I'm not sure what the status is on this, I remember Walter
saying in a conference (DConf 2014 I think) that he had an idea
to remove duplicate template instantiations by comparing their
generated code but I had another idea I thought I'd share.
I'm calling the idea "CombinationTypes". Sort of a
"compile-time" concept that allows code to use multiple types
that would produce the same binary code but retains type
information. The first combination type I would introduce is
the "any*" or "any[]" types. For example, you could write the
following function:
any* limitPtr(any[] array) {
return any.ptr + any.length;
}
This is basically type erasure. It works well reasonably well as
long as only references are allowed. But it seems you want to
allow value types, too.
The advantage of using a combination type like "any" over say
"void" is the compiler knows what you are trying to do and
won't require you to perform any awkward casting. The
following code should work fine:
char[] mychars;
string mystring;
auto mycharsLimit = mychars.limitPtr; // mycharsLimit is a char*
auto mystringLimit = mystring.limitPtr; // mystringLimit is a
immutable(char)*
The generated code for this function will be identical no
matter what the element type is.
Unfortunately not, only if it's an array of byte-sized elements.
If you pass a `wchar[]`, the calculation needs to be <pointer +
2*length> instead of <pointer + length>.
It gets more involved if you want to allow copying and assigning,
because the types can have non-default `this()`, `this(this)`,
`~this()`, `opAssign()`, and so on.
The problem with using a template is that different instances
of this function could be generated (binary code instances)
that are identical. This will probably be compiler dependent
but it would be nice if the programmer could guarantee only one
instance of the function gets generated if that's the effect
they want to achieve.
Furthermore, a CombinationType is much more limiting than a
template which creates less work for the compiler. The
compiler will only need to compile the function once and won't
need to compare the generated binary code of each instance to
remove duplicates.
Another combination type that would be useful is an "anybyte"
type. This would handle both byte and char types (really any
type that uses 1 byte of memory). I'm sure many of the
standard library functions would find this type useful.
I was looking through some of the functions in std.stdio to see
which ones could benefit from this and I realized that a useful
extension to this would be to have a "sizeof" property on the
"any" combination type. You obviously could not access
"any.sizeof" on a function argument inside the function, but
the caller of the function could, so you could use "any.sizeof"
as a default initializer. With this functionality you could
make std.stdio rawRead/rawWrite functions non-template like
this:
Current: T[] rawRead(T)(T[] buffer);
New : size_t rawRead(any[] buffer, size_t elementSize =
any.sizeof);
Current: void rawWrite(T)(in T[] buffer);
New : void rawWrite(any[] buffer, size_t elementSize =
any.sizeof);
This would add an extra runtime argument to the functions vs
having multiple instances each with it's own element size
passed to fread/fwrite so you'd be trading off an extra
function parameter for only one instance of the function. So
this may or may not be the best solution. However I think most
of the time this will be called with 1-byte-element arrays so
you could have 2 instances of it, one with the "anybyte" type
and one with the "any" type. I could see a good argument for
that solution.
One last comment, when you do have a template function it would
be nice if the compiler could guarantee that it would use
combination types when it could. For example, if the original
function limitPtr was written using a template, the compiler
could see that the array is never dereferenced so it knows that
it can use an "any*/any[]" type for the template type so it
only needs to generate one instance of it.
There's probably more useful combination types I haven't
thought of but I'll bring this initial idea to and end and see
if anyone else has anything to say.