Two things I thought would be simple

Shachar Shemesh shachar at weka.io
Thu Mar 8 08:29:49 UTC 2018


On 07/03/18 17:11, Steven Schveighoffer wrote:
> Well, you could do it with templates, but obviously that is less desirable:
> 
> void func2(Args...)(Args args) if(is(typeof(func(args)))) { return 
> func(args); }

I never understood why anyone would use "is" for checking compilability 
when we have "__triats(compiles, func(args))".

With that aside, I would urge you not to use this test. It makes the 
error case worse. Check this out:

void func1(int a) {
}

void func2(Args...)(Args args) if( __traits(compiles, func1(args))) {
    func1(args);
}

void func3(Args...)(Args args) {
    func1(args);
}

void main() {
     long var;

     func2(var);
     func3(var);
}

Which error would you rather get? Calling func2 results in:
test.d(15): Error: template test.func2 cannot deduce function from 
argument types !()(long), candidates are:
test.d(4):        test.func2(Args...)(Args args) if (__traits(compiles, 
func1(args)))

Calling func3 results in:
test.d(9): Error: function test.func1(int a) is not callable using 
argument types (long)
test.d(9):        cannot pass argument _param_0 of type long to 
parameter int a
test.d(16): Error: template instance `test.func3!long` error instantiating

When calling func3, the compiler is telling you what's wrong (i.e. - you 
are passing a long to a function expecting a var). When calling func2, 
all you know is that there is some problem.


With that out of the way, I don't like generating proxy functions with 
"Args..." templates. They generate unneeded code bloat:

void main() {
   int var1;
   ubyte var2;
   byte var3;
   ushort var4;
   short var5;
   uint var6;

   // This generates 6 instantiations of the same function
   func2(var1);
   func2(var2);
   func2(var3);
   func2(var4);
   func2(var5);
   func2(var6);
}

If I could use Params, there would be only one instantiation.


More information about the Digitalmars-d mailing list