Reputation: 17231
I have policies that derive from a base policy. Some classes specialize for the derived policies while others specialize only for the base policy and can work with all derived policies.
The problem I am running into is too much code-duplication (mainly constructors and some boiler plate code for the class itself). The code below may provide a better explanation of what I mean:
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;
};
Is there any way for a derived policy to be accepted by a class specialized for the base policy? I would like the client to not do anything extra.
The following is not valid C++ code, but I would like something like this happen (if you keep the above code in mind):
template<>
struct Foo<BasePolicy | DerivedPolicy1 | DerivedPolicy2>
{
//... many constructors along with code
};
Upvotes: 3
Views: 867
Reputation: 119877
This is a case for SFINAE.
template< typename Policy, ...some_condition... >
struct Foo<Policy>
{
...
};
You should decide what is some_condition exactly. You can specify that Policy derives from BasePolicy:
template< typename Policy, enable_if< is_base<BasePolicy, Policy> > >
Or you can list allowed policies explicitly:
template< typename Policy,
enable_if_c <is_same<Policy, BasePolicy>::value ||
is_same<Policy, DerivedPolicy1>::value> ||
...whatever...
>
>
Upvotes: 5