Two things I thought would be simple

Steven Schveighoffer schveiguy at yahoo.com
Thu Mar 8 10:20:57 UTC 2018


On 3/8/18 3:29 AM, Shachar Shemesh wrote:
> 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))".

There are some subtle differences in the past which caused me not to use 
__traits(compiles).

I don't remember what they are, maybe it's a bias that needs reexamining.

> 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.

Either way, you know the error is in calling func1. In most cases, the 
error is not so simple, and the template is not so simple, to the point 
that I think the first error will be more informative.

It also prevents a problem with template overloading.

> 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.

Yep, hence "obviously that is less desirable."

In an ideal world, there would be a way to remove all traces of func2. 
In other words, there would be a way to instruct the compiler to always 
inline func2, and not even include it in the resulting object file.

-Steve


More information about the Digitalmars-d mailing list