Afaik, у вас есть следующие опции.
Во-первых, если Intermediate
всегда шаблонизируется для производного типа, вам не нужен список для него, потому что он никогда не будет самым производным типом.Если он может быть основан на шаблонах других типов / не может быть получен, вы можете добавить параметр шаблона по умолчанию для нетипичного bool, например, так:
template<bool, class A, class B>
struct select_base{
typedef A type;
};
template<class A, class B>
struct select_base<false,A,B>{
typedef B type;
};
template<class T, bool IsDerived = false>
class Intermediate
: public select_base<IsDerived,
Base<T>,
Base<Intermediate<T> >
>::type
{
// ...
};
// derived use
class Derived : public Intermediate<Derived, true>
{
// ...
};
// non-derived use:
Intermediate<int> im;
Если промежуточный класс не является шаблоном и не является производным от Base
, вам нужно снова получить из Base
в наиболее производном классе:
class Derived : public Intermediate, public Base<Derived>
{
// ...
};
Большая проблема возникает, когда промежуточное звено также происходит от Base
, но не является шаблонным.Вы можете добавить производный тип по умолчанию, но это сделает использование без производных более уродливым:
#include <type_traits> // C++0x, use std::
//#include <tr1/type_traits> // C++03, use std::tr1::
struct nil_base{};
template<class Derived = nil_base>
class Intermediate
: public select_base<std::is_same<Derived,nil_base>::value,
Base<Intermediate<Derived> >, //
Base<Derived>
>::type
{
// ...
};
// derived use now without boolean flag
class Derived : public Intermediate<Derived>
{
// ...
};
// non-derived use a bit uglier
Intermediate<> im;
// ^^ -- sadly needed