Thread overview
Templates with scope
Jul 21, 2021
bauss
Jul 21, 2021
bauss
Jul 21, 2021
Sönke Ludwig
Jul 21, 2021
bauss
Jul 21, 2021
bauss
Jul 21, 2021
drug
Jul 21, 2021
Paul Backus
July 21, 2021

Is there a way to make this logic work without using a mixin template.

I'd prefer if using a plain template was possible, rather than using a mixin template, because it introduces some extra boilerplate.

template CanCompile(alias symbol)
{
    enum CanCompile = __traits(compiles, { mixin(symbol.stringof ~ " = 10;"); });
}

mixin template CanCompile2(alias symbol)
{
    enum couldCompile = __traits(compiles, { mixin(symbol.stringof ~ " = 10;"); });
}

void main()
{
    int x = 20;

    // Fails:
    static if (CanCompile!x)
    {
        x = 10;
    }

    // Okay:
    mixin CanCompile2!x;
    static if (couldCompile)
    {
        x -= 10;
    }

    writeln(x); // Output: 10
}

If it was possible to do it like this:

static if (mixin CanCompile2!x)
{
    x -= 10;
}

Then it wouldn't be a problem, but unfortunately it's not.

I know why the template fails, so I'm not looking for the reasoning behind it, but is there not a way to avoid using mixin templates because I don't want to introduce a variable into the scope and I want to keep the code as short as possible.

Basically my use-case is just to test if certain expressions are possible in the current scope based on a given symbol, but I'd want to just test it in a static if statement.

I'm aware that I can just put the __traits(compiles) directly into the code, but what I'm trying to achieve here is a wrapper around that so I don't have some ugly boilerplate code.

July 21, 2021
>

...

This was meant to be in learn...

July 21, 2021
Am 21.07.2021 um 09:16 schrieb bauss:
> Is there a way to make this logic work without using a mixin template.
> 
> I'd prefer if using a plain template was possible, rather than using a mixin template, because it introduces some extra boilerplate.

The symbol name is not available in the scope of the template, so that the `mixin(symbol.stringof)` doesn't work, but you can simply use the alias directly:

    template CanCompile(alias symbol)
    {
        enum CanCompile = __traits(compiles, { symbol = 10; });
    }

July 21, 2021
But why do you think that `CanCompile` fails? It works for me:
```D
template CanCompile(alias symbol)
{
    enum CanCompile = __traits(compiles, { symbol = 10; });
}

mixin template CanCompile2(alias symbol)
{
    enum couldCompile = __traits(compiles, { symbol = 10; });
}

void main()
{
    int x = 20;

    static if (CanCompile!x)
    {
        x = 9;
    }

    assert(x == 9);

    mixin CanCompile2!x;
    static if (couldCompile)
    {
        x = 12;
    }

    assert(x == 12);
}
```
July 21, 2021
On Wednesday, 21 July 2021 at 09:06:52 UTC, Sönke Ludwig wrote:
> Am 21.07.2021 um 09:16 schrieb bauss:
>> Is there a way to make this logic work without using a mixin template.
>> 
>> I'd prefer if using a plain template was possible, rather than using a mixin template, because it introduces some extra boilerplate.
>
> The symbol name is not available in the scope of the template, so that the `mixin(symbol.stringof)` doesn't work, but you can simply use the alias directly:
>
>     template CanCompile(alias symbol)
>     {
>         enum CanCompile = __traits(compiles, { symbol = 10; });
>     }

The problem is that I just saw I didn't describe my problem very well, as I don't actually have the symbol at the given time.

I only had the symbol name and I use it to test if the symbol is available because it comes from a __traits(allMembers) which includes some symbols that makes it fail to compile if I try to use the symbol directly without checking whether it compiles or not.

And this was the exact template I was trying to use:

```d
template CanUseSymbol(string symbolName, string symbolAlias = "symbol", string moduleAlias = "moduleImport")
{
  enum CanUseSymbol = __traits(compiles, { mixin("alias " ~ symbolAlias ~ " = " ~ moduleAlias ~ "." ~ symbolName ~ ";"); });
}
```

For obvious reasons it doesn't work as you also mentioned, the scope simply isn't available.

But I can't use alias unfortunately in this case.

I wish there was a way to return the symbols from allMembers, instead of just the name of the symbols, that would solve this problem.
July 21, 2021
On Wednesday, 21 July 2021 at 10:08:10 UTC, bauss wrote:
> On Wednesday, 21 July 2021 at 09:06:52 UTC, Sönke Ludwig wrote:
>> Am 21.07.2021 um 09:16 schrieb bauss:
>>> Is there a way to make this logic work without using a mixin template.
>>> 
>>> I'd prefer if using a plain template was possible, rather than using a mixin template, because it introduces some extra boilerplate.
>>
>> The symbol name is not available in the scope of the template, so that the `mixin(symbol.stringof)` doesn't work, but you can simply use the alias directly:
>>
>>     template CanCompile(alias symbol)
>>     {
>>         enum CanCompile = __traits(compiles, { symbol = 10; });
>>     }
>
> The problem is that I just saw I didn't describe my problem very well, as I don't actually have the symbol at the given time.
>
> I only had the symbol name and I use it to test if the symbol is available because it comes from a __traits(allMembers) which includes some symbols that makes it fail to compile if I try to use the symbol directly without checking whether it compiles or not.
>
> And this was the exact template I was trying to use:
>
> ```d
> template CanUseSymbol(string symbolName, string symbolAlias = "symbol", string moduleAlias = "moduleImport")
> {
>   enum CanUseSymbol = __traits(compiles, { mixin("alias " ~ symbolAlias ~ " = " ~ moduleAlias ~ "." ~ symbolName ~ ";"); });
> }
> ```
>
> For obvious reasons it doesn't work as you also mentioned, the scope simply isn't available.
>
> But I can't use alias unfortunately in this case.
>
> I wish there was a way to return the symbols from allMembers, instead of just the name of the symbols, that would solve this problem.

I found a somewhat solution to it all by creating a template that used __traits(allMembers) and in the same scope tested the members and built a new list of members that were available and then simply used the generated list to loop through, so I didn't have to test the symbols outside of the template's scope.
July 21, 2021

On Wednesday, 21 July 2021 at 07:16:43 UTC, bauss wrote:

>

Is there a way to make this logic work without using a mixin template.

I'd prefer if using a plain template was possible, rather than using a mixin template, because it introduces some extra boilerplate.

enum CanCompile(alias symbol) =
    `__traits(compiles, { ` ~ symbol.stringof ~ ` = 10; })`;

void main()
{
    int x = 20;
    static if (mixin(CanCompile!x))
    {
        x = 10;
    }
}