In D, when a template has a member with the same name as the template, any instantiation of the template refers directly to that member. But if that member is itself a template, I cannot immediately instantiate it for some reason. Creating an intermediate alias works, however.
template Foo(int x){
template Foo(int y){
enum int Foo = x+y;
}
}
alias Foo1 = Foo!(1);
assert(Foo1!(2) == 3); // ok
int a = Foo!(1)!(1); // compile error Error: found '!' when expecting ')'
Why does this fail? Is there any way around this?
My goal is neatness and currying.
This is how D grammar is defined. Current compiler shows correct error message:
Error: multiple ! arguments are not allowed
Also this question is already filed as Issue 1566 and from issue comment 4:
If I don't miss something multiple
!
is considered harmful asA!B!C
may be considered asA
instantiated withB!C
orA!B
instantiated withC
. Also requirement to always have parantheses in such case may be added but IMO it doesn't look like a worthwhile language complication as it isn't generally needed.
This can be workarounded by e.g. such Inst
template:
template Foo(int x)
{ enum int Foo(int y) = x + y; }
alias Inst(alias Template, A...) = Template!A;
enum a = Inst!(Foo!1, 1);
Note D now has a new short template declaration syntax and also one doesn't need to use parantheses in case template argument is an identifier or a constant.