C++: Design Pattern using templates, Policy-Based Class

Strategy Pattern

Strategy Pattern is a behavioral pattern, that allows one to change the behavior of an object at run time. Below is my favorite representation of the pattern. I tried to keep it as close as possible to the original image from the book “Head First Design Patterns”

Strategy Design Pattern

I love this pattern because of its simplicity and flexibility it offers. As in this example, one can create any type of duck by extending from base class Duck. If you need a different fly behavior for your new duck class, just create a new fly behavior by extending abstract FlyBehavior and associate the new behavior with your new class.

This pattern nicely complies with SOLID principles; Specially Single-Responsibility Principle (SRP) and Open-closed Principle (OCP).

  • FlyBehaviors taking care of fly behaviors / algorithms, QuackBehaviors taking care of quack behaviors / algorithms and Ducks taking care of their duck business. That’s SRP.
  • Now OCP says objects or entities should be open for extension but closed for modification. Here to change a behavior one doesn’t need to change anything in Duck. To create a new type of duck you only extend. Also, one can change the behavior at run-time simply by changing one behavior with another compatible behavior.

Like most object oriented patterns, Strategy pattern depends on inheritance and will rely on virtual functions. Accessing them comes with additional cost. So, if you are building a high performant library it can become the reason for a performance bottle-neck. Policy-Based Class Design is a pattern that make use of templates to achieve what Strategy pattern did for us.

Policy-Based Class Design

The Basic

Let’s see the same example with the help of Policy-Based Class Design, a design pattern using templates. You will see how it achieves the same effect as Strategy pattern. Here the Behavior or algorithms are called policies and their implementations are in policy classes. The classes that uses one or more policies are called hosts or host classes.

Policy classes

struct FlyNoWay {
    void fly() {
        std::cout << "I can't fly!\n";
    }
}

struct FlyWithWings {
    void fly() {
        std::cout << "I am flying!\n";
    }
}

Host classes

template <typename FlyPolicy>
class Duck: public FlyPolicy {
public:
    Duch() = default;
};

The Usage of Policy-Based Class Design

Duck<FlyWithWings> realDuck;
Duck<FlyNoWay> rubberDuck;

realDuck.fly();    // I am flying!
rubberDuck.fly();  // I can't fly!

Templates are good for creating combinational behaviors as they generate code at compile time based on the types provided by the used. This design takes advantage of this feature. Additionally, class templates are customizable in ways not supported by regular classes. If you want to implement a special case, you can use specialization.

Generic Programming style

Let’s look at another example. We will define a policy for creating objects. The Creator policy dynamically creates an object of type T. The policy must expose a member function called Create() that returns a pointer to T. Each call to Create() should return a pointer to a new object of type T. The way in which the object is created vary from policy to policy. One Policy can make use of operator new and the other malloc().

template <class T>
struct OpNewCreator
{
   static T* Create() {
      std::cout<< "OpNewCreator: ";
      return new T;
   }
};

template <class T>
struct mallocCreator
{
   static T* Create() {
      
      void* buff = std::malloc(sizeof(T));
      if (!buff) return nullptr;
      return new(buf) T;  // Construct a `T` object, placing it 
                          // directly into your pre-allocated 
                          // storage at memory address `buf`.
   }
};

Lets have a simple class whose objects we would like to create.

class Widget {
};

Now lets see how to implement the host for these policies.

template <class CreationPolicy>
class WidgetManager : public CreationPolicy {
};

int main() {
   std::cout << "Output:\n"

   typedef WidgetManager< OpNewCreator<Widget> > MyWidgetMgr;

   MyWidgetMgr aWidgetMgr;
   Widget* aWidgetPtr = nullptr;
   aWidgetPtr = aWidgetMgr.Create();
   std::cout << static_cast<void*>(aWidgetPtr) << '\n';
}

The output would like like this:

Output:
OpNewCreator: 0x999420

Using template template parameter

Here we will be using template template parameter, as shown below:

template <template <typename ToCreate> class CreationPolicy>
class OtherWidgetManager : public CreationPolicy<Widget>
{
};

CreationPolicy is the templte template parameter. Here is the syntax:

Syntax:
   template <typename> class T

Here,
    the keyword class is mandatory, and 
    cannot be replaced with typename

Meaning:
    Class T is a class template, with a
    single type name parameter

Now lets see how to use it:

template <template <typename ToCreate> class CreationPolicy>
class OtherWidgetManager : public CreationPolicy<Widget>
{
};

int main() {
   std::cout << "Output:\n"

   typedef OtherWidgetManager<MallocCreator> OtherWidgetMgr;

   OtherWidgetMgr anOtherWidgetMgr;
   aWidgetPtr = anOtherWidgetMgr.Create();
   std::cout << static_cast<void*>(aWidgetPtr) << '\n';
}

The output would like like this:

Output:
MallocCreator: 0x999440

There is one more thing that can be done. How about we want to have a default behavior for our host, say in most cases we need operator new for creating our object. Below is how we can do this:

template <template <typename> class CreationPolicy = OpNewCreator>
class NewWidgetManager : public CreationPolicy<Widget>
{
};

int main() {
   std::cout << "Output:\n"

   NewWidgetManager<> aNewWidgetMgr;

   aWidgetPtr = aNewWidgetMgr.Create();
   std::cout << static_cast<void*>(aWidgetPtr) << '\n';
}

The output will be:

Output:
OpNewCreator: 0x999440

Note:

Once I was asked if Policy-based class design same as Curiously Recurring Template Pattern (CRTP)? The answer is no, they are not same. They may look very similar but here is what is needed for CRTP:

  • inheriting from a template class
  • use the derived class itself as a template parameter of the base class // this is where it differs
template <typename T>
class Base
{
    //...
};

class Derived : public Base<Derived>
{
    //...
};

We will talk about Curiously Recurring Template Pattern (CRTP) some other day!

Additionally, such design provides you with a faster runtime but can slow down your compile time, as you ask your compiler to do all the heavy liftings. Compilation can become resource hungry, specially in terms of memory.

Resource:

If you are interested in some of the advanced usage of templates, may be you will like these books:

Also if you are interested in templates, you can check my post on function templates.