Reputation: 4850
[temp.param] p11 says (in N4527):
(...) A template parameter pack of a function template shall not be followed by another template parameter unless that template parameter can be deduced from the parameter-type-list of the function template or has a default argument
In the context of non-type template parameter packs, there can't be default arguments,
so what exactly needs to be deduced for the packs (just the type, or the values, too)?
i.e. I'm wondering if this is allowed by the standard (C++11, 14 or 1z):
template<typename T, T... A, T... B>
void foo(T) {}
The first pack's values could be explicitly specified, but the second pack is "unreachable" and would always be empty if I'm not mistaken.
clang++-3.6 and g++-5.2 seem to accept these empty unreachable packs (even non non-type packs), but VC++ 14.0 refuses them with the error:
error C3547: template parameter 'B' cannot be used because it follows a template parameter pack and cannot be deduced from the function parameters of 'foo'
Upvotes: 7
Views: 1687
Reputation: 303337
No, it not allowed by the standard. From [temp.param]:
A template parameter pack of a function template shall not be followed by another template parameter unless that template parameter can be deduced from the parameter-type-list of the function template or has a default argument (14.8.2). [Example:
template<class T1 = int, class T2> class B; // error // U can be neither deduced from the parameter-type-list nor specified template<class... T, class... U> void f() { } // error template<class... T, class U> void g() { } // error
—end example ]
In your case, ...B
cannot be deduced (as there's nothing to deduce it from) and it has no default argument.
so what exactly needs to be deduced for the packs (just the type, or the values, too)?
For example, if your foo
was:
template <size_t... A, size_t... B>
void foo(std::index_sequence<B...> );
...A
is followed by ...B
, but ...B
can be deduced, so that's allowed. Similarly:
template <typename T, T... A, T B = 0>
void foo();
is fine, as B
has a default argument.
Upvotes: 5