It seems that a pack argument can be expanded only in the place of a pack parameter of an alias template. This is not true for a class or a function template:
template <class T, class... Args> struct x { using type = T; };
template <class T, class... Args> using x_t = typename x<T, Args...>::type;
template <class... Args> using x_fix_t = typename x<Args...>::type;
template <class... Args> auto f(Args...) -> void {
typename x<Args...>::type v1; // OK
x_t<Args...> v2; // Error
x_fix_t<Args...> v3; // OK
}
simpler case:
template <class T, class U> using y_t = T;
template <class... Args> auto f(Args...) -> void {
y_t<Args...> v4; // Error
}
The above code generates error (even if f
is never instantiated) with both c++11
and c++14
in g++ 4.9
, g++ 5.1
and clang 3.5
.
Why is this not permitted and what is the general rule? I see no reason to restrict this. It seems a very strange prohibition.
As for why not writing as x_fix_t
with the first variant it is more clear that x_t
has a mandatory first argument. (for instance that is the reason f()
is not permitted). But this is not that important, the fix is easy. The question remains: Why?
gcc error:
error: pack expansion argument for non-pack parameter ‘T’ of
alias template ‘template<class T, class ... Args> using x_t = typename x::type’
clang error:
error: pack expansion used as argument for non-pack parameter of
alias template x_t<Args...> v2;
This compiles in GCC 4.8 but fails in GCC 4.9, which is evidence that it's related to DR1430 and bug report #59498. The fix proposed by Roy Chrihfield is the exact same one as yours:
Furthermore, Jason Merrill elaborates on why it should fail:
No further discussion exists in the bug report, so we can turn to DR1430:
In otherwords, this is an on-going issue without any resolution (AFAIC) in sight.