Click here to Skip to main content
15,878,814 members
Articles / Programming Languages / C++11
Tip/Trick

Policy Design Pattern and Variadic Template Technique

Rate me:
Please Sign up or sign in to vote.
5.00/5 (3 votes)
8 Apr 2015CPOL2 min read 18.3K   7   2
This article presents simple combination of Policy design pattern and Variadic Template Technique.

Introduction

Every software developer in C++ is faced with the generic programming. Some of them have started to use the Policy design pattern. I have spent much time on research of that pattern and found an interesting form of it with the feature of C++11 - Variadic template technique.  

Background

I have spent much time on research of Policy design pattern and implemented it once in one commercial project. However, some time ago, I decided to improve my project by including C++11 features and found a very nice form for Policy pattern.

Using the Code

The new form of Policy pattern can have the next form:

C++
template<typename... Policies>
class PolicyAndVaradic: public Policies{};

This form is different from the old form:

C++
template<typename PolicyOne, typename PolicyTwo>
class PolicyOldForm: public PolicyOne, PolicyTwo{};

It leads to the interesting idea - it is possible to create a class which amount of policies is resolved in the time of compiling. 

So, you can ask - how it can be used? I wrote a simple code:

C++
template<typename... Policies>
class PolicyAndVariadic: public Policies...{};

class PolicyOne
{
public:
    void executePolicyOne()
    {
        std::cout << "execute PolicyOne" << std::endl;    
    }
};

class PolicyTwo
{
public:
    void executePolicyTwo()
    {
        std::cout << "execute PolicyTwo" << std::endl;
    }
};

typedef PolicyAndVariadic<PolicyOne, PolicyTwo> PolicyOneAndPolicyTwo;

PolicyOneAndPolicyTwo linstance;

linstance.executePolicyOne();

linstance.executePolicyTwo();

As you see, in the code the template class PolicyOneAndPolicyTwo includes implementation of classes PolicyOne and PolicyTwo via the template PolicyAndVariadic. In old style, the amount of Policies was limited by old standards of C++. The C++11 allows to get more nice view policy template class. 

You can ask - it works perfectly with default constructors, but what to do if we want to include policies, which constructors have to arguments? It leads to the next nice view form:

C++
template<typename... Policies>
class PolicyAndVaradic: public Policies...
{
public:
    template<typename... Args>
    PolicyAndVaradic(const Args... Arg)
        : Policies(Arg)...{}
};

class PolicyOne
{
    std::string mText;

public:
    PolicyOne(const char* aText):mText(aText){}
    
    void executePolicyOne()
    {
        std::cout << mText << std::endl;
    }
};

class PolicyTwo
{
    std::string mText;
public:

    PolicyTwo(const char* aText):mText(aText){}

    void executePolicyTwo()
    {
        std::cout << mText << std::endl;
    }
};

PolicyOneAndPolicyTwo linstance("PolicyOne", "PolicyTwo");

linstance.executePolicyOne();

linstance.executePolicyTwo();

So, I think that I do not need to explain how it works.

Of course, you can say the every serious library on policy pattern needs more complex actions with the policies and this form cannot be suitable. I agree with it. However, if you want to create a simple template solution with static polymorphism, then the policy pattern with variadic template can be a suitable solution.

Points of Interest

I think that it could be interesting to include a Lambda expression pattern into the policy pattern.

History

  • 8th April, 2015: Initial version

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer
Australia Australia
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
QuestionVariadic Policues Pin
geoyar13-Apr-15 13:34
professionalgeoyar13-Apr-15 13:34 
AnswerRe: Variadic Policues Pin
Evgeny Pereguda13-Apr-15 20:00
Evgeny Pereguda13-Apr-15 20:00 
Hi,

I see your doubt about using such trick for simple solution. If you need only simple template for solving local problem with generalization - then your suggestion about of template execute() is suitable (I often use it in my code). However, if you have started to design big (or not) project then it may be smart to spend some time on design of policy pattern - more about it you can find in book "Modern C++ Design" of Andrei Alexandrescu. From my experience I used policy pattern in the next simple form (this simple example I have wrote for you on basement of my experience):
C++
#include <QString>
#include <QtTest>

#include <iostream>

#include "policyandvaradic.h"

class Animation
{
    std::string mText;

public:

<pre>
Animation(const char* aText):mText(aText){}

void executePolicyOne()
{
    std::cout &lt;&lt; mText &lt;&lt; std::endl;
}

};

class OpenGLDesktop
{
std::string mText;
public:
OpenGLDesktop(const char* aText):mText(aText){}

void executePolicyTwo()
{
    std::cout &lt;&lt; mText &lt;&lt; std::endl;
}

};

class OpenGLES1_1
{
std::string mText;
public:
OpenGLES1_1(const char* aText):mText(aText){}

void executePolicyTwo()
{
    std::cout &lt;&lt; mText &lt;&lt; std::endl;
}

};

typedef PolicyAndVaradic<Animation, OpenGLDesktop> AnimationAndOpenGLDesktop;

typedef PolicyAndVaradic<Animation, OpenGLES1_1> AnimationAndOpenGLES1_1;

class PolicyAndVaradicUnitTest : public QObject
{
Q_OBJECT

public:
PolicyAndVaradicUnitTest();
template&lt;typename... Policies&gt; void execute(PolicyAndVaradic&lt;Policies...&gt; aPolicyAndVaradic)
{
    aPolicyAndVaradic.executePolicyOne();

    aPolicyAndVaradic.executePolicyTwo();
}

private Q_SLOTS:
void testCase1();
};

PolicyAndVaradicUnitTest::PolicyAndVaradicUnitTest()
{
}

void PolicyAndVaradicUnitTest::testCase1()
{
AnimationAndOpenGLDesktop linstance("Animation", "OpenGLDesktop");
AnimationAndOpenGLES1_1 linstanceOpenGLES1_1("Animation", "OpenGLES1_1");

linstance.executePolicyOne();

linstance.executePolicyTwo();

execute(linstance);

execute(linstanceOpenGLES1_1);

}

QTEST_APPLESS_MAIN(PolicyAndVaradicUnitTest)

#include "tst_policyandvaradicunittest.moc"


This is the Unit test for Qt, but it reflects the problem which I faced in the project and solution of it. The project included 3D graphic and the original target platforms was Linux and Windows. The graphic was placed into the special library and it was compiled into DLL or SO. However, after some days of design the company had decided to expand the solution on Android platform via Android NDK, and I had faced with the problem - OpenGL ES 1.1 does not support OpenGL 3.0 of desktop version. I decided that it is dummy to develop two different projects for Android and Desktop, which code is the same on 90 percent. More over, after fixing of mistake in that 90 percent in one project it needs to merging the 90 percent of code into other. I have understood that OpenGL supporting and other 90 percent of code are 'orthogonal' - OpenGL support does not depend from other code, and other code does not depend from OpenGL support. It allows to use policy pattern. From the code below you can see that the needed classes AnimationAndOpenGLDesktop and AnimationAndOpenGLES1_1 are collected at the time compiling of code as a model from LEGO blocks:

C++
#ifdef OPENGLDESKTOP
typedef PolicyAndVaradic<Animation, OpenGLDesktop> AnimationAndOpenGLDesktop;
#else
typedef PolicyAndVaradic<Animation, OpenGLES1_1> AnimationAndOpenGLES1_1;
#endif

The accessibility of blocks are defined by PreCompile variable OPENGLDESKTOP which define supporting of type. Of course, OpenGLDesktop and OpenGLES1_1 can be inherited from the one united Interface IDraw. However, I would like to point your attention on the next code:
C++
template<typename... Policies> void execute(PolicyAndVaradic<Policies...> aPolicyAndVaradic)
{
    aPolicyAndVaradic.executePolicyOne();

    aPolicyAndVaradic.executePolicyTwo();
}
The argument PolicyAndVaradic<Policies...> aPolicyAndVaradic has signature which define any template class, which created from PolicyAndVaradic<Policies...>. However, compiler will compile this method only with template class which implements methods executePolicyOne() and executePolicyTwo(). As a result, any policy classes can implement these methods, and they will be processed in the same way - so, it is a conception of polymorphism, but without table of virtual functions - this is static polymorphism (it is like static_cast differ from dynamic_cast).

Sorry for such long answer, but it is the simplest way to explain why I have decided to write this article. More ideas you can find in the mentioned above book. I can only say that Policy pattern cannot resolve all problem, but it is powerful pattern and if you start new project it can be smart to lay the pattern into the basement of it.

With best,
Evgeny

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.