I have a set of classes that are chained using a member typedef Next
, as follows:
class Y; class Z;
class X { public: typedef Y Next; };
class Y { public: typedef Z Next; };
class Z { };
I need a way to get the final class of a chain, starting from any class of the chain. Thanks to the accepted answer of this post, I wrote the following code:
// cond_type<Condition, Then, Else>::type // selects type 'Then' if 'Condition' is true, or type 'Else' otherwise
template <bool Condition, typename Then, typename Else = void>
struct cond_type
{
typedef Then type;
};
template <typename Then, typename Else>
struct cond_type<false, Then, Else >
{
typedef Else type;
};
template <class C, typename _ = void>
struct chain
{
typedef C last;
};
template <class C>
struct chain<C, typename cond_type<false, typename C::Next>::type>
{
typedef typename chain<typename C::Next>::last last;
};
Using the above template chain<C>::last
, the following code properly instantiates 3 objects of class Z
, as expected:
chain<X>::last z1;
chain<Y>::last z2;
chain<Z>::last z3;
However, if the considered set of classes form an inheritance hierarchy, in the following way:
class U; class V;
class T { public: typedef U Next; };
class U : public T { public: typedef V Next; };
class V : public U { };
Then, using template chain<C>::last
, with any class C
of the above set, for example:
chain<T>::last v;
result in the following compile error:
1>test.cpp(88): error C3646: 'last' : unknown override specifier
I understand that the problem is that class V
inherits from typedef V Next
defined in the parent class U
, resulting in compilation of the specialized form of the template chain<V,V>
while the generic one should be used instead as V
has no member Next
.
Anyway, I am stuck here, as I need a mechanism that works, even in this case of a class hierarchy.
How could I do this ?
PS: inheritance between classes must remain public; member typedefs must remain public.