__traits(compiles, ...) with syntax errors

Steven Schveighoffer schveiguy at gmail.com
Wed Jan 16 14:43:29 UTC 2019


On 1/15/19 6:59 AM, Petar Kirov [ZombineDev] wrote:
> On Tuesday, 15 January 2019 at 11:15:21 UTC, Atila Neves wrote:
>> On Monday, 14 January 2019 at 21:47:40 UTC, Steven Schveighoffer wrote:
>>> How many times have you written something like:
>>
>> More times than I can count...
>>
>>>
>>> void foo(T)(T t) if (__traits(compiles, t.bar())) // or 
>>> is(typeof(t.bar()))
>>> {
>>>    t.bar();
>>> }
>>>
>>> [...]
>>
>> I'm not sure how best to go about this.
> 
> Sounds like a job for `static try` too keep things DRY:
> 
> void fun(T)(T t) if (__traits(compiles, t.foo()))
> {
>      t.foo();
> }
> 
> void fun(T)(T t) if (__traits(compiles, t.bar()))
> {
>      t.bar();
> }
> 
> // ----v
> 
> void fun(T)(T t)
> {
>      static try { t.bar(); }
>      else static try { t.foo(); }
>      else static assert(0, T.stringof ~ "does not support neither `foo`, 
> nor `bar`");
> }

It might be nice to have something like this. Note that the two code 
samples aren't equivalent -- something that defines both bar and foo 
would not work with the first iteration, but would work with the second.

The DRYness of the constraint is annoying too, but this misses the point 
that t.bar and t.foo may be intended to BOTH compile, but only one does 
because of a "stupid" error. And so the wrong path is taken, and you 
either get weird other errors, or you get no errors, but the code 
doesn't work right or is unintentionally lower performance.

Understanding WHY a template constraint fails is important, but when you 
have __traits(compiles), it's a very blunt instrument. There are so many 
reasons why it might not compile, and it's really hard to figure out the 
answer, especially if you don't control the templates. Overriding the 
constraints might be the easiest way to probe the answers out.

-Steve


More information about the Digitalmars-d mailing list