Fallback 'catch-all' template functions

Timon Gehr via Digitalmars-d digitalmars-d at puremagic.com
Thu Sep 1 11:24:13 PDT 2016


On 01.09.2016 19:55, Meta wrote:
> On Thursday, 1 September 2016 at 17:49:13 UTC, Timon Gehr wrote:
>> On 01.09.2016 19:21, Meta wrote:
>>> ...
>>>
>>> I just thought of this, but cannot test if it works. If it does, maybe
>>> it would be a suitable solution?
>>>
>>> void f(T)(T t) if(isSomething!T) {}
>>> void f(T)(T t) if(isSomethingElse!T) {}
>>> //Taken if no other "overload" of f will intantiate with the given T
>>> void f(T)(T t) if(!__traits(compiles, alias _ = .f!T)) {}
>>
>> It shouldn't work, but DMD currently seems to allow it. (If you fix
>> the syntax error.) I would expect it to break later.
>>
>>
>> The following causes an ICE (DMD segfaults).
>>
>> import std.stdio;
>>
>> int f(T)(T t) if(!__traits(compiles,.f!T)) {
>>     return 0;
>> }
>> int f(T)(T t) if(!__traits(compiles,.f!T)) {
>>     return 1;
>> }
>>
>> void main(){
>>     writeln(f(2));
>> }
>
> The idea is that there'd only be one such "fallback" template, so that
> you cannot get into a situation such as this. I'm guessing the ICE is
> due to a recursive dependency between the two f templates?

I posted the ICE to show that DMD does not necessarily have a clear 
concept of how your code should be interpreted. Note that you are 
essentially saying: "If not X then X". It's very easy to run into 
behaviour that seems inconsistent once you do things like this.

enum isSomething(T)=false;

int f(T)(T t) if(isSomething!T){
     return 0;
}
int f(T)(T t) if(!compiles!".f!int") {
     return 2;
}

enum compiles(string s) = __traits(compiles,mixin(s));
pragma(msg, compiles!".f!int");         // false
pragma(msg, __traits(compiles,.f!int)); // true


DMD cannot properly process code like this (i.e. code that contradicts 
itself, where the same expression in the same context can be true in one 
part of the compilation, but false later). Examples can be constructed 
where the semantics of the resulting code depends on the order that 
modules are passed on the command line. It's not specified anywhere what 
should happen, and it is not immediately clear.

DMD shouldn't accept code like this in the first place. It's very 
brittle, the result depends on random compiler implementation details.


More information about the Digitalmars-d mailing list