Search code examples
c++templatesc++11c++14policy

Shortening template arguments in policy based refactoring


I am trying to refactor some code using policies (see the book Modern C++ Design) and want to shorten or simplify the code for the methods of the host classes. Let's say I have an already implemented class named Hostclass:

// Hostclass header, start version
struct Hostclass {
    void Hostfct1();
    void Hostfct2();
    ...
};
// method definitions, start version
void
Hostclass::Hostfct1(){...}

void
Hostclass::Hostfct2(){...}
...

Now I have a policy class

struct Policy1class {
    void Policy1fct(){};
};

and want to inject Policy1class into Hostclass. This means I have to change the Header of Hostclass:

// Hostclass header, second version
template <typename Policy1>
struct Hostclass : public Policy1 {

But what about the methods? Hostclass is now a template class, so the function definitions demand another specifier:

// method definitions, second version
template <typename Policy1>
void
Hostclass<Policy1>::Hostfct() {...}
...

Now I want to enrich Hostclass further with another policy

struct Policy2class {
    void Policy2fct(){};
};

so I have to change the header again:

// Hostclass header, third version
template <typename Policy1, typename Policy2>
struct Hostclass : public Policy1, Policy2 {

as well as the specifier:

// method definitions, third version
template <typename Policy1, typename Policy2>
void
Hostclass<Policy1,Policy2>::Hostfct() {...}
...

I think changing all specifiers of all hostclass methods everytime a new policy enters the stage is a bit a pain in the ass. Is it possible, perhaps with the new tools of C++14 and its template aliases or extern template, to simplify this method definition? I have something like this

// invalid code
class P1;
class P2;
using H = Hostclass<P1,P2>;
// method definitions, dream version
void
H::Hostfct1() {...}

void
H::Hostfct2() {...}
...

in mind. The only other option I could think of to circumvent the definition specifications is to implement a HostclassWrapper class which inherits itself from Hostclass and all other policies:

// Hostclass header, start version
struct Hostclass {...};
// method definitions, start version
void
Hostclass::Hostfct1(){...}
// new wrapper class
template <typename Policy1, typename Policy2>
class HostclassWrapper : public Hostclass, Policy1, Policy2 {
};

Any other suggestions?


Solution

  • You could simply use variadic templates:

    template <class... Policies>
    class Host : public Policies... { ... }
    
    template <class... Policies>
    void Host<Policies...>::func() { ... }
    

    The only way around avoiding repeating the template declaration in each of the member function definitions would be to just define them all in the class definition itself.

    But if you're supporting some arbitrary number of policies, a variadic template is definitely what you want.