Incorrect use of std::conditional
std::conditonal<condition, true-type, false-type>
Your problem boils down to the fact that both true and false types in std::conditional should give a valid name, regardless of which side chooses the condition.
Note It proposes a proposed solution at the end of this post if a full explanation is not required.
Consider the following example:
struct A { typedef int type; }; struct B { };
template<class T> struct some_trait { typedef typename std::conditional< std::is_same<T, A>::value, typename T::type, void >::type result; };
Running some_trait<A> will be absolutely correct, but what happens if we create it with B ?
template<> struct some_trait<B> { typedef typename std::conditional< std::is_same<B, A>::value, typename B::type,
In the above example, we claim to be a compiler, and we replaced every T event with B , this is not all that works hard, but it raised a very important problem with our main template.
When the compiler instantiates some_trait<T> using T = B , the true-type in our std::conditional will be B::type (A).
But since B does not have a name inside it called type , we get a compiler diagnostics saying that something is wrong with our code, namely; we are trying to access a name that does not exist.
foo.cpp:15:37: error: no type named 'type' in 'B' /* true-type -> */ typename T::type, // (A), ill-formed
Proposed solution
In fact, there is no doubt what we should do, and briefly; do not let our template access names that do not potentially exist.
An easy way to do this is to use explicit specialization instead of using std::conditional .
back implementation example
template<typename TypeList> struct back { typedef typename back<typename TypeList::Tail>::type type; }; template<typename T> struct back<type_list<T>> { typedef typename type_list<T>::Head type; };
Note If an instance of template<typename T> struct back; is type_list with only one parameter, we know that we are on the last node.