New blog post on the cost of compile time

Steven Schveighoffer schveiguy at gmail.com
Thu Jan 19 15:19:06 UTC 2023


On 1/18/23 5:20 PM, Walter Bright wrote:
> On 1/17/2023 1:58 PM, H. S. Teoh wrote:
>> If the
>> language had instead been extended so that you could, for example,
>> extract the return type of some given callable directly, say
>> typeof(return(myfunc)), then none of this would have been necessary in
>> the first place.
> 
> https://dlang.org/spec/expression.html#is_expression
> 
>      int func();
> 
>      static if (is(typeof(func) R == return))
>          pragma(msg, R);
> 
> prints:
> 
>      int
> 
> The implementation of std.traits.ReturnType is:
> 
>      template ReturnType(alias func)
>      if (isCallable!func)
>      {
>          static if (is(FunctionTypeOf!func R == return))
>              alias ReturnType = R;
>          else
>              static assert(0, "argument has no return type");
>      }
> 
> ReturnType can do a little more than the raw IsExpression, as it can 
> identify:
> 
>      struct G
>      {
>          int opCall (int i) { return 1;}
>      }
> 

I didn't think of making ReturnType simplified (we know in this case the 
thing is not anything except a normal lambda function). I did this now:

```d
template RT(alias sym) {
     static if(is(typeof(sym) R == return))
         alias RT = R;
     else
         static assert(false, "bad");
}

...

else version(useIsExpr)
{
     enum isInputRange(R) = is(typeof(R.init) == R)
     && is(RT!((R r) => r.empty) == bool)
     && (is(typeof((return ref R r) => r.front)) || is(typeof(ref 
(return ref R r) => r.front)))
     && !is(RT!((R r) => r.front) == void)
     && is(typeof((R r) => r.popFront));
}
```

The result is still not as good as just using typeof directly, but much 
much better. When compared to a direct typeof, it adds about 0.15s of 
total compile time for 10000 instances, and adds 100MB more memory usage.

My point still stands -- *inside* a constraint template, you should 
avoid using all kinds of convenience templates if you can help it. 
Nobody cares about the implementation of `isInputRange`, as long as it 
gives the right answer.

Now, Adam has a point (in his comment on my blog) that if you are 
*already* using such convenience templates elsewhere on the *same 
parameters*, then this can have a negative effect on overall 
performance, because the caching of the template answer can speed up the 
compilation. In this case, the template instantiation is guaranteed to 
be unique since these are lambda expressions, so that doesn't apply.

I think we can all agree though that it is less than ideal to have to 
worry about the internal details of how templates are implemented.

-Steve


More information about the Digitalmars-d mailing list