I don't think you can let Plate
be the most derived type, as that would mean the overall type would have to have itself as one of its own template parameters. This is the closest I've gotten:
struct Empty {};
template <template <class> class Head, template <class> class... Tail>
struct GenLinearHierarchy
{
typedef Head<typename GenLinearHierarchy<Tail...>::type> type;
};
template <template <class> class Tail>
struct GenLinearHierarchy<Tail>
{
typedef Tail<Empty> type;
};
template <class Base> struct A : Base {};
template <class Base> struct B : Base {};
template <class Base> struct C : Base {};
template <class Base> struct D : Base {};
static_assert(std::is_same< typename GenLinearHierarchy<A,B,C,D>::type
, A<B<C<D<Empty>>>> >::value
, "");
EDIT I think I've got what you wished for. Good luck trying to read it. You've only got yourself to blame. :)
struct Empty {};
template <class MostDerived,
template <class, class> class Head,
template <class, class> class... Tail>
struct GenLinearHierarchyInner
{
typedef Head<typename GenLinearHierarchyInner<MostDerived,
Tail...>::type,
MostDerived> type;
};
template <class MostDerived,
template <class, class> class Tail>
struct GenLinearHierarchyInner<MostDerived, Tail>
{
typedef Tail<Empty, MostDerived> type;
};
template <template <class, class> class... Types>
struct GenLinearHierarchy : GenLinearHierarchyInner<GenLinearHierarchy<Types...>,
Types...>::type
{};
template <class Base, class> struct A : Base {};
template <class Base, class> struct B : Base {};
template <class Base, class> struct C : Base {};
template <class Base, class> struct D : Base {};
typedef GenLinearHierarchy<A,B,C,D> ABCD;
static_assert(std::is_base_of< A<B<C<D<Empty, ABCD>, ABCD>, ABCD>, ABCD>
, ABCD >::value
, "");