I have a class template, expecting some other template as a parameter:
template<
class Key,
template <typename K,template <typename T> class Allocator> class Policy
>
class container {
Policy<Key,Allocator>* _policy;
//some code here
};
and usually i use it with the policy class like this:
template <class Key,template <typename T> class Allocator> class policy {
//some code
};
but what if i have to pass additional template parameter to policy class? Something like:
template <time_t Age,class Key,template <typename T> class Allocator> class policy_3 {
//some code
};
What can i do, to allow users of that class, pass the Age paratemeter without touching others? For example:
typedef container<key_type,policy_3<100500> > containerWithAge;
You have two options: binding, and rebinding.
In binding, you adapt the ternary policy into a binary one, as expected by the template-template parameter Policy
:
template <typename Key, template <typename T> class Allocator>
struct policy_3_100500 : ternary_policy<100500,Key,Allocator> {};
and use policy_3_100500
instead of policy_3<100500>
.
To be closer to the syntax you're shooting for, you can use a nested class:
template <time_t Age>
struct policy_3 {
template <typename Key, template <typename T> class Allocator>
struct type : ternary_policy<Age,Key,Allocator> {};
};
and use policy_3<100500>::type
instead of policy_3<100500>
.
The only way to get exactly the syntax you want is to move the ::type
into the class using the policy. That's the second option: rebinding (this is also used in std::allocator, btw). In this case, you pass the Policy
as a normal template parameter, and assume a template metafunction, say bind
, to exist:
template <time_t Age>
struct policy_3 {
template <typename Key, template <typename T> class Allocator>
struct bind : ternary_policy<Age,Key,Allocator> {};
};
While structually identical to the second option, the difference lies in who calls bind
: In the first option (binding), it's the user of the policy class (by passing policy<100500>::type
explicitly). Here, it's the class using the policy:
template <typename Key, typename Policy>
struct container {
typename Policy::template bind<Key,std::allocator<Key>> * _policy;
// ...
}:
As a general note, Policy classes are not usually passed as template-template arguments, but as normal template arguments (precisely because they may have a varying number of arguments themselves). The classes using the policy then assume a certain inner structure (typedefs, functions, meta functions, constants) to be present in the policy, of which bind
is just an example.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With