Template Instantiation Bug

Jonathan Marler via Digitalmars-d digitalmars-d at puremagic.com
Tue Nov 4 15:01:39 PST 2014


On Tuesday, 4 November 2014 at 21:48:29 UTC, Walter Bright wrote:
> On 11/4/2014 9:51 AM, Jonathan Marler wrote:
>> given the
>> output of Transform, the compiler cannot deduce what the input 
>> of Transform was
>> EVEN IF THE TEMPLATE IS AS SIMPLE AS THIS ONE.
>
> To answer a question not asked, why doesn't the compiler see 
> the simple case and handle it?
>
> The problem is that this becomes a special case in the language 
> specification, making the language harder to understand. Cue 
> bug reports of people confused about why the simpler cases work 
> and the more complex ones do not, and they overall get a 
> negative impression of the language. And I don't blame them.


Yes, trying to reverse the logic inside a template in the GENERAL 
case would likely be next to impossible, or at least, require 
alot of work/code to support something thay may not be very 
useful. And if you can't solve the general case, I agree you 
shouldn't support the simple cases.

However, I'll bring up the reason I wanted this functionality in 
case you have another solution.  I wanted to create a template 
that used different parameter attributes depending on the type.  
For example, I just submitted a pull request to phobos to 
optimize the put/doPut functions in std.range 
(https://github.com/D-Programming-Language/phobos/pull/2655) to 
only use ref OutputRange when necessary.  For types like 
pointers, classes, delegates, and functions, the ref attribute is 
unnecessary and can inhibit compiler optimization.  For my pull 
request, the only solution I could come up with was to have 2 
instances of each function with a template guard that handles ref 
and non-ref paramters:

private template isPassByValue(T)
{
     enum bool isPassByValue =
		isPointer!T ||
		is( T == class ) ||
		is( T == delegate ) ||
		is( T == function ) ;
}

void put(R, E)(R r, E e) if( isPassByValue!R )
{
// put code
}
void put(R, E)(ref R r, E e) if( !isPassByValue!R )
{
// exact same put code
}

There's got to be a better way to do this.  If anyone has any 
ideas let me know.


More information about the Digitalmars-d mailing list