Передача частично специализированного шаблона в качестве параметра шаблона - PullRequest
4 голосов
/ 26 апреля 2011

У меня есть шаблон класса, ожидающий какой-то другой шаблон в качестве параметра:

template<
    class Key, 
    template <typename K,template <typename T> class Allocator> class Policy
>
class container {
     Policy<Key,Allocator>* _policy;
     //some code here
};

, и обычно я использую его с классом политики следующим образом:

template <class Key,template <typename T> class Allocator> class policy {
    //some code
};

, но что еслия должен передать дополнительный параметр шаблона в классе политики?Что-то вроде:

template <time_t Age,class Key,template <typename T> class Allocator> class policy_3 {
    //some code
};

Что я могу сделать, чтобы пользователи этого класса могли передавать параметр возраста, не касаясь других?Например:

typedef container<key_type,policy_3<100500> > containerWithAge;

1 Ответ

8 голосов
/ 26 апреля 2011

У вас есть два варианта: привязка и повторная привязка.

В привязке вы адаптируете троичную политику в двоичную, как того требует параметр шаблона-шаблона Policy:

template <typename Key, template <typename T> class Allocator>
struct policy_3_100500 : ternary_policy<100500,Key,Allocator> {};

и используйте policy_3_100500 вместо policy_3<100500>.

Чтобы быть ближе к синтаксису, по которому вы стреляете, вы можете использовать вложенный класс:

template <time_t Age>
struct policy_3 {
    template <typename Key, template <typename T> class Allocator>
    struct type : ternary_policy<Age,Key,Allocator> {};
};

и использоватьpolicy_3<100500>::type вместо policy_3<100500>.

Единственный способ получить именно тот синтаксис, который вам нужен, - это переместить ::type в класс, используя политику.Это второй вариант: перепривязка (это также используется в std :: allocator, btw).В этом случае вы передаете Policy в качестве обычного параметра шаблона и предполагаете, что метафункция шаблона, скажем, bind, существует:

template <time_t Age>
struct policy_3 {
    template <typename Key, template <typename T> class Allocator>
    struct bind : ternary_policy<Age,Key,Allocator> {};
};

Хотя это структурно идентично второму варианту, разница заключаетсяв котором вызывает bind: в первом варианте (связывание) это пользователь класса политики (передавая явно policy<100500>::type).Здесь это класс, использующий политику:

template <typename Key, typename Policy>
struct container {
    typename Policy::template bind<Key,std::allocator<Key>> * _policy;
    // ...
}:

Как общее примечание, классы политики обычно передаются не как аргументы шаблона-шаблона, а как обычные аргументы шаблона (именно потому, что они могут иметь различное числосами аргументы).Классы, использующие политику, предполагают, что в политике присутствует определенная внутренняя структура (typedefs, функции, мета-функции, константы), из которых bind является просто примером.

...