Получение специализации класса шаблона на основе работы базовой политики для всех производных политик

У меня есть политики, производные от базовой политики. Некоторые классы специализируются на производных политиках, в то время как другие специализируются только на базовой политике и могут работать со всеми производными политиками.

Проблема, с которой я сталкиваюсь, заключается в слишком большом количестве дублирования кода (в основном конструкторы и некоторый шаблонный код для самого класса). Код ниже может дать лучшее объяснение того, что я имею в виду:

struct BasePolicy {};
struct DerivedPolicy1 : public BasePolicy {};
struct DerivedPolicy2 : public BasePolicy {};
//... more policies deriving from BasePolicy (or other BasePolicies)
struct AnotherPolicy {};

template <typename T>
struct Foo;

// This struct can work for all BasePolicy types which includes all derivations
// of it (but doesn't because it is specialized for BasePolicy only)
template<>
struct Foo<BasePolicy>
{
  //... many constructors along with code
};

template<>
struct Foo<AnotherPolicy>
{
  //... more code
};

/* Would like to avoid the following code as it duplicates the above when it 
   comes to constructors and other things such as typedefs */
//template<>
//struct Foo<DerivedPolicy1> : Foo<BasePolicy>
//{
//  //... same constructors as Foo<BasePolicy>
//};
//
//template<>
//struct Foo<DerivedPolicy2> : Foo<BasePolicy>
//{
//  //... same constructors as Foo<BasePolicy>
//};

int main()
{
  // would like this to compile without uncommenting the commented out code and
  // without having the client (i.e. the line below) to somehow get the base
  // type of the policy (although if it can be done transparently, that will
  // work)
  Foo<DerivedPolicy1> a; 
};

Есть ли способ, чтобы производная политика была принята классом, специализированным для базовой политики? Я бы хотел, чтобы клиент не делал ничего лишнего.

Следующий код недействителен на С++, но я бы хотел, чтобы произошло что-то подобное (если вы помните приведенный выше код):

template<>
struct Foo<BasePolicy | DerivedPolicy1 | DerivedPolicy2>
{
  //... many constructors along with code
};

person Samaursa    schedule 11.03.2012    source источник


Ответы (1)


Это случай для SFINAE.

template< typename Policy, ...some_condition... >
struct Foo<Policy>
{
 ...
};

Вы должны решить, что такое some_condition. Вы можете указать, что Policy происходит от BasePolicy:

template< typename Policy, enable_if< is_base<BasePolicy, Policy> > >

Или вы можете указать разрешенные политики явно:

template< typename Policy,
           enable_if_c <is_same<Policy, BasePolicy>::value || 
                         is_same<Policy, DerivedPolicy1>::value> || 
                         ...whatever...
                        >
         >
person n. 1.8e9-where's-my-share m.    schedule 11.03.2012
comment
Просто сам столкнулся с этой же проблемой; ты сказал это так хорошо, как я мог. :) - person Nick; 11.03.2012
comment
Отлично, именно то, что я искал. - person Samaursa; 12.03.2012