Less Code Bloat from Templates

via Digitalmars-d digitalmars-d at puremagic.com
Thu Oct 30 06:44:44 PDT 2014


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.



More information about the Digitalmars-d mailing list