I implemented a "discriminated union" capable of holding C++ types, even if they have destructors etc. I implemented this as a Russian doll; i.e. Union<T1, T2, T3> derives from unionNode<T1, <UnionNode<T2, UnionNode<T3, void> > > and UnionNode<T, Tail> derives from Tail. The specialization UnionNode<T, void> holds a void* which contains the actual data, and an index to store the current type.
For quite a few functions, I'd like a meta-function to determine if a type U is one of the types T1..Tn. For instance, I've got a member template<typename U> union_cast<U> that should only be instantiated for types that could actually be in the union. Trying to cast a Union to std::string is a compile-time error.
The simple solution was to add a template <typename U> struct inUnion :
template <typename T, typename Tail> // Tail will be a UnionNode too.
struct UnionNode : public Tail {
// ...
template<typename U> struct inUnion {
typedef Tail::inUnion<U> dummy; // <<< Q: where to add typename/template here?
};
template< > struct inUnion<T> {
};
};
template <typename T> // For the last node Tn.
struct UnionNode<T, void> {
// ...
template<typename U> struct inUnion {
char fail[ -sizeof(U) ]; // Cannot be instantiated for any U
};
template< > struct inUnion<T> {
};
};
The idea is simple, I think: Each UnionNode<T, Tail> defines a template specialization inUnion<T>, and forwards the generic case inUnion<U>. If in the last node, no specialization of inUnion<U> has been found, then U is not one of the types T1...Tn, and I try to typedef an array with negative size. The problem I have is in the typedef Tail::inUnion<U> dummy line. I'm fairly certain that inUnion is a dependent name, and VC++ is quite right in choking on it. I also know that I should be able to add "template" somewhere to tell the compiler that inUnion is a template-id. But where exactly? And should it then assume that inUnion is a class template, i.e. inUnion<U> names a type and not a function?