Thread overview
Templates with scope
Jul 21
bauss
Jul 21
bauss
Jul 21
bauss
Jul 21
bauss
Jul 21
drug
July 21

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
>

...

This was meant to be in learn...

July 21
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
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
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
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

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;
    }
}