Template constraints should introduce identifiers inside their scopes
HuskyNator
HuskyNator at protonmail.ch
Wed Sep 21 11:23:57 UTC 2022
Consider these semantically identical functions:
```d
void foo(M)(M list) {
static if (is(M : T[L], T, uint L)) {
pragma(msg, "Length: " ~ L.to!string); // Length: 2
}
}
void bar(M)(M list) if (is(M : T[L], T, uint L)) {
pragma(msg, "Length: " ~ L.to!string); // undefined identifier
'L'
}
void main(string[] args) {
int[2] list = [1, 2];
foo(list);
bar(list);
}
```
Although semantically the same, `bar` will fail.
This can of course be solved by changing the template arguments,
but could lead to issues in more complex scenarios:
```d
alias UnsignedType(T) = mixin(getUnsignedType!(T));
string getUnsignedType(T)() {
static if (is(T == byte))
return "ubyte";
else static if (is(T == short))
return "ushort";
else static if (is(T == int))
return "uint";
else
assert(0, "Type not supported: " ~ T.stringof);
}
auto foo(T)(T number) if (is(UnsignedType!T T2)) {
alias T2 = UnsignedType!T; // still required
return cast(T2) number;
}
void main(string[] args) {
foo(1).writeln; // 1
foo(-1).writeln; // 4294967295
}
```
Apart from these examples, depending on complexity, one might
even think of a scenario in which a type returned inside the
template condition should be matched against, in which case the
body of the function would be required to contain a duplicate
statement:
`is(aliasMixin!M M2: T[L], T, uint L);` (eg. when getUnsignedType
returns a more complex type)
---
Given the above consideration, assuming this is not a bug (tested
on both dmd & ldc), I believe identifiers introduced inside a
template constraint should be visible inside the scope of the
template.
More information about the Digitalmars-d
mailing list