www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Templates with scope

reply bauss <jj_1337 live.dk> writes:
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.

```d
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:

```d
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.
Jul 21 2021
next sibling parent bauss <jj_1337 live.dk> writes:
 ...
This was meant to be in learn...
Jul 21 2021
prev sibling next sibling parent reply =?UTF-8?Q?S=c3=b6nke_Ludwig?= <sludwig outerproduct.org> writes:
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; }); }
Jul 21 2021
parent reply bauss <jj_1337 live.dk> writes:
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.
Jul 21 2021
parent bauss <jj_1337 live.dk> writes:
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.
Jul 21 2021
prev sibling next sibling parent drug <drug2004 bk.ru> writes:
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);
}
```
Jul 21 2021
prev sibling parent Paul Backus <snarwin gmail.com> writes:
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.
```d enum CanCompile(alias symbol) = `__traits(compiles, { ` ~ symbol.stringof ~ ` = 10; })`; void main() { int x = 20; static if (mixin(CanCompile!x)) { x = 10; } } ```
Jul 21 2021