Thread overview
DRY version of `static if(__traits(compiles, expr)) fun(expr)`
Dec 13, 2016
Timothee Cour
Dec 13, 2016
Timon Gehr
Dec 14, 2016
Basile B.
Dec 14, 2016
Ali Çehreli
Dec 15, 2016
Basile B.
Dec 15, 2016
Timon Gehr
December 13, 2016
what's the best (and DRY) way to achieve:

```
static if(__traits(compiles, expr))
  fun(expr);
```

ie, without repeating the expression inside expr?

eg:

```
static if(__traits(compiles, foo.bar[2])){
  counter++;
  writeln(" expr = ", foo.bar[2]);
}

```


December 14, 2016
On 14.12.2016 00:00, Timothee Cour via Digitalmars-d-learn wrote:
> what's the best (and DRY) way to achieve:
>
> ```
> static if(__traits(compiles, expr))
>   fun(expr);
> ```
>
> ie, without repeating the expression inside expr?
>
> eg:
>
> ```
> static if(__traits(compiles, foo.bar[2])){
>   counter++;
>   writeln(" expr = ", foo.bar[2]);
> }
>
> ```
>

I usually do

enum code = q{expr};
static if(__traits(compiles,mixin(code)))
    fun(mixin(code));

December 14, 2016
On Tuesday, 13 December 2016 at 23:37:59 UTC, Timon Gehr wrote:
> On 14.12.2016 00:00, Timothee Cour via Digitalmars-d-learn wrote:
>> what's the best (and DRY) way to achieve:
>>
>> ```
>> static if(__traits(compiles, expr))
>>   fun(expr);
>> ```
>>
>> ie, without repeating the expression inside expr?
>>
>> eg:
>>
>> ```
>> static if(__traits(compiles, foo.bar[2])){
>>   counter++;
>>   writeln(" expr = ", foo.bar[2]);
>> }
>>
>> ```
>>
>
> I usually do
>
> enum code = q{expr};
> static if(__traits(compiles,mixin(code)))
>     fun(mixin(code));

Strangely if i put this in a templated enum that doesn't work.
If instead i use a delegate literal it works.

enum Compiles(string code) = is(typeof((){mixin(code);}));

enum Compiles2(string code) = __traits(compiles, mixin(code));

unittest
{
    static assert(Compiles!q{auto a = 1+1;});
    static assert(!Compiles!q{1;});
    static assert(!Compiles!q{a = 1;});

    static assert(Compiles2!q{auto a = 1+1;});
    static assert(!Compiles2!q{1;});
    static assert(!Compiles2!q{a = 1;});
}

wtf ?
December 14, 2016
On 12/14/2016 09:25 AM, Basile B. wrote:
> On Tuesday, 13 December 2016 at 23:37:59 UTC, Timon Gehr wrote:

>> I usually do
>>
>> enum code = q{expr};
>> static if(__traits(compiles,mixin(code)))
>>     fun(mixin(code));
>
> Strangely if i put this in a templated enum that doesn't work.
> If instead i use a delegate literal it works.
>
> enum Compiles(string code) = is(typeof((){mixin(code);}));
>
> enum Compiles2(string code) = __traits(compiles, mixin(code));

When you do that, the code does not match the syntax of __traits(compiles). Putting the code inside a scope works at least in this case:

enum Compiles2(string code) = __traits(compiles, mixin('{' ~ code ~ '}'));

Ali

December 15, 2016
On Wednesday, 14 December 2016 at 22:06:35 UTC, Ali Çehreli wrote:
> On 12/14/2016 09:25 AM, Basile B. wrote:
> > On Tuesday, 13 December 2016 at 23:37:59 UTC, Timon Gehr
> wrote:
>
> >> I usually do
> >>
> >> enum code = q{expr};
> >> static if(__traits(compiles,mixin(code)))
> >>     fun(mixin(code));
> >
> > Strangely if i put this in a templated enum that doesn't work.
> > If instead i use a delegate literal it works.
> >
> > enum Compiles(string code) = is(typeof((){mixin(code);}));
> >
> > enum Compiles2(string code) = __traits(compiles, mixin(code));
>
> When you do that, the code does not match the syntax of __traits(compiles). Putting the code inside a scope works at least in this case:
>
> enum Compiles2(string code) = __traits(compiles, mixin('{' ~ code ~ '}'));
>
> Ali

I see, it makes sense. Anyway the two templates have a common problem (protection attributes: data used in the code must be visible to the outside), so using them as a shortcut is a false good idea.
December 15, 2016
On 15.12.2016 01:38, Basile B. wrote:
> On Wednesday, 14 December 2016 at 22:06:35 UTC, Ali Çehreli wrote:
>> On 12/14/2016 09:25 AM, Basile B. wrote:
>> > On Tuesday, 13 December 2016 at 23:37:59 UTC, Timon Gehr
>> wrote:
>>
>> >> I usually do
>> >>
>> >> enum code = q{expr};
>> >> static if(__traits(compiles,mixin(code)))
>> >>     fun(mixin(code));
>> >
>> > Strangely if i put this in a templated enum that doesn't work.
>> > If instead i use a delegate literal it works.
>> >
>> > enum Compiles(string code) = is(typeof((){mixin(code);}));
>> >
>> > enum Compiles2(string code) = __traits(compiles, mixin(code));
>>
>> When you do that, the code does not match the syntax of
>> __traits(compiles). Putting the code inside a scope works at least in
>> this case:
>>
>> enum Compiles2(string code) = __traits(compiles, mixin('{' ~ code ~
>> '}'));
>>
>> Ali
>
> I see, it makes sense. Anyway the two templates have a common problem
> (protection attributes: data used in the code must be visible to the
> outside), so using them as a shortcut is a false good idea.

Shortcut that works:

enum ifCompiles(string code)=`static if(__traits(compiles,{ `~code~` })){ `~code~` }`;

mixin(ifCompiles!q{ ... });