Часто увлекаясь метапрограммированием, я могу рекомендовать только "многословный" подход, но мне не очень нравится первый подход, который вы предлагаете.
В идеале, когда вы используете Политики, вы не просто передаете флаг, вы передаете объект Политики, который позволит пользователю настраивать его по своему желанию, а не полагаться на ваши собственные предопределенные значения.
Например:
struct NodeCheckerTag {};
struct CheckEveryNode {
typedef NodeCheckerTag PolicyTag;
void check(List const& list);
};
struct CheckFirstNode {
typedef NodeCheckerTag PolicyTag;
void check(List const& list);
};
template <typename Rand>
struct CheckSomeNodes {
typedef NodeCheckerTag PolicyTag;
CheckSomeNodes(Rand rand): _rand(rand) {}
void check(List const& list);
Rand _rand;
};
Таким образом, ваш класс должен позволять пользователю выбирать, какую политику выбрать:
template <typename NodeChecker>
class X: NodeChecker // allow stateful implementation but let EBO kick in
{
};
PolicyTag
- наличие нескольких политик:
template <typename NodeChecker, typename NodeAllocator, typename NodeNotifier>
class X;
Обычно вы должны предоставить разумные значения по умолчанию, но всегда есть случай Я хочу настроить только последний! , переключившись на шаблон с переменным числом, вы можете получить следующее:
template <typename Tag, typename Default, typename... Policies>
struct PolicySelector
{
typedef /**/ type;
};
template <typename... Policies>
class X: Policies...
{
typedef typename PolicySelector<NodeCheckerTag, CheckNoNode,
Policies...>::type NodeCheckerPolicy;
typedef typename PolicySelector<NodeAllocatorTag, StdAllocator,
Policies...>::type NodeAllocatorPolicy;
...
};
Обратите внимание, что при наследовании от политик выбор может быть ненужным, если вы заботитесь только о вызове некоторых функций. Это необходимо, только если вам нужны внутренние определения типов, скрытые в политиках, так как они должны быть явно определены в производном классе (здесь X).