3
votes

Does D support template template parameters? How would I get the following to work?

struct Type(alias a, alias b) { alias a A; alias b B; }

template MakeType(alias a, alias b)
{
  alias Type!(a, b) MakeType;
}

template Foo(alias a, U) // where U is a Type
{
  //...
}

template Foo(alias a, U : MakeType!(a, b), b...)  // where U is a specialization
{
  //...
}

and Foo is supposed to be called as such:

alias MakeType!(5, 7) MyType;
alias Foo!(5, MyType) Fooed;  // error

Error: template instance Foo!(5,Type!(5,7)) Foo!(5,Type!(5,7)) does not match template declaration Foo(alias a,U : MakeType!(a,b),b...)

1
Note: in my actual case, a and b are not simple integer values; they are instances of user-defined types. - Arlen
The goal here is to get b filled in from the rest of the arguments to MakeType, right? You could check it manually: "template Foo(alias a, U, b...)if(is(U == MakeType!(a, b)))" works with "alias Foo!(5, MyType, 7) Fooed;" but both and and b are given explicitly. Now, if MyType had a member that was type b, you could get that out easily enough, not as a template param but just as the member. Like so: arsdnet.net/thingy.d - Adam D. Ruppe
@AdamD.Ruppe I can't give both a and b explicitly. MyType can have alias to both a and b, and I changed the code to reflect that. Also note, the U in Foo is a specialization. - Arlen

1 Answers

5
votes

I got it working :-)

template Foo(alias a, U) // where U is a Type
{
  //...
}
template Foo(alias a, U : X, X) if(is(X == MakeType!(a, U.B)))
{
  //...
}

and in usage:

alias MakeType!(1, 3) MyType1;
alias MakeType!(5, 7) MyType2;
Foo!(5, MyType1) // calls the first Foo()
Foo!(5, MyType2) // calls the second Foo() with specialization