c++templatesvariadic-templatestemplate-inheritance

Combining Policy Classes - Template Template Parameters & Variadic Templates


I am wondering if it's possible to combine policy classes using variadic template-template parameters such that each policy may have it's own template pack. It seems like you can only share a single template pack amongst all policies but I hope that's not the case.

The following seems to be what's possible:

template <
    class T,
    template <class, typename...>   class Policy1,
    template <class, typename...>   class Policy2,
    template <class, typename...>   class Policy3,
    typename... Args    
>
struct PolicyClass 
    : public Policy1     <ObjT, Args...>
    , public Policy2     <ObjT, Args...>
    , public Policy3     <ObjT, Args...>    {}

I'm hoping each policy can have it's own pack so I could make something like this (?):

template <class T>
struct implementedPolicy1 {};
template <class T>
struct implementedPolicy2 {};
template <class T, class A>
struct implementedPolicy3 {};

PolicyClass <ObjT, 
             implementedPolicy1,
             implementedPolicy2,
             implementedPolicy3<AType>
            >

The idea being each of the policies are all using the same object type but the third has some further templating. I know that's incorrect code above - just trying to illustrate what I'd like to be able to do.

Thanks


Solution

  • You need to be able to delimit between the packs.

    // helper template.  Using `std::tuple<>` instead is another option.
    template<class...>struct type_list {};
    
    // base, note no body:
    template <
        class T,
        template <class, typename...>   class Policy0,
        template <class, typename...>   class Policy1,
        template <class, typename...>   class Policy2,
        typename... Packs
    >
    struct PolicyClass;
    
    // specialization:
    template <
        class T,
        template <class, typename...>   class Policy0,
        template <class, typename...>   class Policy1,
        template <class, typename...>   class Policy2,
        typename... A0s,
        typename... A1s,
        typename... A2s
    >
    struct PolicyClass<
      T, Policy1, Policy2, Policy3,
      type_list<A0s...>, type_list<A1s...>, type_list<A2s...>
    >
    : Policy0<T, A0s...>, Policy1<T, A1s...>, Policy2<T, A2s...> {}
    

    where I pack each policies extra arguments into a type_list.

    In theory you could do fancier things, like have particular "tag" types being the delimiters, but it ends up being a lot of gymnastics.

    PolicyClass< int, bob, eve, alice, type_list<>, type_list<double>, type_list<char, char, char> > foo;
    

    will create

    PolicyClass: bob<int>, alice<int, double>, eve<int, char, char, char>
    

    roughly.