Template sequence parameters (Ts...
) must be the last parameter of a template. That also means one can only have one of them per template.
To facilitate passing a sequence to a sequence parameter, a new syntactical construct is needed. For simplicity, I’ll use !()
. It would only be needed if a template with a non-terminal sequence parameter is explicitly instantiated.
void f(Ts..., Rs...)(Ts ts, Rs rs) { }
f(); // Ts = !(), Rs = !()
f(1,2,3); // Ts = !(int, int, int), Rs = !()
f!(!(int))(1,2,3); // Ts = !(int), Rs = !(int, int)
f!(!(int), !(int, long))(1,2,3); // Ts = !(int), Rs = !(int, long)
f!(!int, int, long)(1,2,3); // Ts = !(int), Rs = !(int, long)
// The `()` are optional if it’s a single token
// The last sequence matches individually stated arguments (current behavior)
Other use case: Make it hard to pass certain arguments
void f(Ts..., size_t line = __LINE__)(Ts args) { pragma(msg, line); }
f!(int, int)(1, 2); // good, Ts = !(int, int)
f!(int, int, 0)(1, 2); // error, tries Ts = !(int, int, 0), but `0` is not a type
f!(!(int, int), 0)(1, 2); // good (won’t happen by accident)
Note: !(Args…)
would not produce an AliasSeq!(Args…)
. It’d be part of the template argument list syntax:
TemplateInstance:
Identifier TemplateArguments
TemplateArguments:
! ( )
! ( TemplateArgumentList )
! TemplateSingleArgument
TemplateArgumentList:
TemplateArgument
TemplateArgument ,
TemplateArgument , TemplateArgumentList
TemplateArgument:
Type
AssignExpression
Symbol
+ TemplateArguments