Reputation: 1322
In my previous question (Is it legal to use an unexpanded parameter pack as the type of a template template parameter's non-type template parameter?), it was pointed out that it is not legal to expand a parameter pack in the same template parameter list it was declared in, per [temp.param]/17. However, the question still stands when the expansion is done in a separate parameter list. In the following code:
template <typename... Args>
struct tuple {};
template <typename... Types>
struct A {
template <typename>
struct B;
};
template <typename... Types>
template <
template <Types> typename... Outer, // XXX
Types... Inner
>
struct A<Types...>::B<tuple<Outer<Inner>...>> {};
template <long T> struct O1 {};
template <unsigned T> struct O2 {};
A<long, unsigned>::B<tuple<O1<1>, O2<2>>> test;
clang accepts the code, deducing Types = {long, unsigned}, Outer = {O1, O2}, Inner={1L, 2U}. Structurally, this seems correct.
gcc ICEs on the code, while MSVC and ICC reject it.
Is this code valid? On the line denoted XXX
, is it valid to have a parameter pack as the type of the template template parameter's non-type template parameter?
Upvotes: 6
Views: 257
Reputation: 621
It seems to me, that your code valid.
Please, refer to the standard. page 370, (5.3.1).
Your code on the XXX-line is the pack expansion pattern, that is the parameter-declaration.
Also, Types
shouldn't be considered here as the parameter pack itself, it's an inner part of the expansion pattern, so there is no "parameter pack as the type".
Also, rule about expansion pack in it's template clause from your previous question shouldn't be violated, because you have two different templates, when compiler expands inner template, Types
from outer template must be already inferred.
Anyway, as for me, it's a weird, that gcc ICEs and msvc rejects this code.
Upvotes: 1