I am following C templates the complete guide and trying to get the first element from a typelist.
The following compiles:
#include <bits/stdc .h>
using namespace std;
template <typename... Elements>
class Typelist;
using SignedIntegralTypes =
Typelist<signed char, short, int, long, long long>;
template <typename List>
class HeadT;
template <typename Head, typename... Tail>
class HeadT<Typelist<Head, Tail...>> {
public:
using Type = Head;
};
template <typename List>
using Head = typename HeadT<Typelist<List>>::Type;
int main() {
static_assert(is_same<Head<SignedIntegralTypes>, SignedIntegralTypes>::value, "");
}
Head<SignedIntegralTypes>
produces SignedIntegralTypes
. I would expect it to produce signed char
. Why is this happening? How do I fix it?
CodePudding user response:
Let's deconstruct all the templates, one step at a time.
Head<SignedIntegralTypes>
Ok, now let's take the definition of what Head
is:
template <typename List>
using Head = typename HeadT<Typelist<List>>::Type;
Since SignedIntegralTypes
is the template parameter, that's what List
becomes here. So this becomes:
typename HeadT<Typelist<SignedIntegralTypes>>::Type
And since SignedIntegralTypes
is, itself a:
using SignedIntegralTypes =
Typelist<signed char, short, int, long, long long>;
The full class becomes:
typename HeadT<Typelist<Typelist<signed char, short, int, long, long long>>>::Type
And if you work out the result of the specialization, the first type in the Typelist
is
Typelist<signed char, short, int, long, long long>
And that's what Type
gets aliased to. A.k.a. a SignedIntegralTypes
.
And you fix this, to get the intended result, simply by fixing the Head
alias:
template <typename List>
using Head = typename HeadT<List>::Type;