Reputation: 1604
I may write as
template< class T0> struct Last0
{
using type = decltype(T0{}); // OK compiles. `type = T0`
};
template< class T0, class T1> struct Last1
{
using type = decltype(T0{}, T1{}); // OK, compiles. `type = T1`
};
template< class T0, class T1, class T2> struct Last3{
using type = decltype(T0{}, T1{}, T2{}); // Ok, compiles. `type = T2`
};
But, when I use variadic templates, it's not compiled:
template< class ... T> struct Last{
using type = decltype(T{} ... ); //<--- Error !!!
};
What's problem?
Upvotes: 6
Views: 5007
Reputation: 171127
There is a taxative list of language constructs where pack expansion can happen (C++11, 14.5.3§4). With the exception of sizeof...
, it's always in constructs where the comma ,
is a grammatical separator of a list, and not an operator. An expression cannot be a pack expansion.
To get the last type in a pack, you can do this:
template <class Head, class... Tail>
struct Last {
typedef typename Last<Tail...>::Type Type;
};
template <class Head>
struct Last<Head> {
typedef Head Type;
};
Upvotes: 5
Reputation: 477080
You can only apply decltype
to an expression, not to a pack. Packs are very special and basically always need to be expanded. You essentially have the same problem as not being able to store packs directly: using type = T...
isn't allowed, either.
The standard solution is to store packs inside some "container template", typically tuple
:
using T = std::tuple<decltype(T{})...>;
Upvotes: 3