I think both versions are not equivalent at all. Consider [1]:
```
import std.meta;
void main()
{
pragma(msg, __traits(getMember, A, "Foo1").stringof); // Foo1(int
N) if (N & 1)
pragma(msg, __traits(getAttributes, __traits(getMember, A,
"Foo1"))[0]); // tuple("int", "odd")
alias f1a = Instantiate!(__traits(getMember, A, "Foo1"), 1); //
This is expected
pragma(msg, f1a); // A
alias f1b = Instantiate!(__traits(getMember, A, "Foo1"), "+"); //
Why would I know that I can even instantiate?? Also, can I haz UDA plz?
pragma(msg, f1b); // B
}
class A {
@("int", "odd")
template Foo1(int N) if (N & 1) {
enum Foo1 = "A";
}
@("string", "+")
template Foo1(string op) if (op == "+") {
enum Foo1 = "B";
}
}
```
In this case you could perhaps use an alias parameter to achieve a
similar effect. I haven't tried it but it would be really messy, if it
even works.
What seems clear to me from this case is that *internally* the compiler
sees a *set* of "overloads" (change that word if you think it should
only apply to functions), but I can only get the first of the batch!
For example, I might want to add some information in the UDA on how to
instantiate the template, but then I can't get the UDA either. I'm sure
it's somewhere, just that we get no access to it, and that shouldn't be
too hard to add.
I think this clarifies a bit the problem I see.
A.
[1]: https://run.dlang.io/is/zRDHGn
On 04/23/2018 05:00 PM, Alex wrote:
On Monday, 23 April 2018 at 14:22:13 UTC, Simen Kjærås wrote:
As with all things D, the only real spec is the compiler source code.
:p :(
:p
Proving that two templates are equivalent is in general impossible,
since any amount of wasted computation could be performed before the
end result is returned, and inputs must be tested exhaustively for the
proof to be valid. The fact that two templates give the same result in
one special case does not mean that they are equivalent in the general
case, and the compiler needs to care about the general case.
Ok, thats exactly the point. If you have functions
void foo() {}
void foo(int n) {}
There is no ambiguity which function will be chosen if it will be called.
If you have templates
// form 1
template Foo(int N) if (N & 1) {} // A
template Foo(int N) if (!(N & 1)) {} // B
OR
// form 2
template foo(int N)
{
static if(N & 1){} // A
else{} // B
}
There is also no ambiguity which will be called.
However, getOverloads will behave differently.
This is not bad at all. But you have to admit, that while now, there is
no way to distinguish form 1 and form 2, with the new getOverloads there
will be.
This seems strange to me, because there is no reason to distinguish form
1 and form 2. (Because the callable code, which will be generated is the
same, I hope... ?)
So, in particular, I'm not against the feature. And if the equivalence
between form 1 and form 2 is gone, so what. But I don't understand the
reasoning why something which is now equal won't be equal any more later?