11

I am trying to understand the real requirement of the usage of templates for policy based design. Going through the new templated designs in C++ I found that policy based class design is a highly suggested way of design which allows you to 'plug-in' different behaviors from policy classes. A minimal example is the following (a shortened version of the wiki):

template <typename LanguagePolicy>
class HelloWorld : private LanguagePolicy
{
    using LanguagePolicy::message;

public:
    // Behaviour method
    void run() const
    {
        // policy methods
        cout << message();
    }
};

class LanguagePolicyA
{
protected:
    std::string message() const
    {
        return "Hello, World!";
    }
};
//usage
HelloWorld<LanguagePolicyA> hello_worlda;
hello_worlda.run(); // prints "Hello, World!"

A quick analysis shows that just to get different plugable methods message() we are inheriting from a templated type whose definition can be provided by anyone (and identified at compile time).

But the same level of abstraction (and configurable methods) can be achieved without using a templated code and by the simple old school run time polymorphism as shown below.

class HelloWorld
{
    LanguagePolicy *lp; //list of all plugable class
public:
    HelloWorld(LanguagePolicy *lpn) {
        lp = lpn;
    }

    // Behaviour method
    void run() const
    {
        // policy methods
        cout << lp->message();
    }
};
class LanguagePolicy
{
protected:
    virtual std::string message() const;
};

class LanguagePolicyA: LanguagePolicy
{
protected:
    std::string message() const
    {
        return "Hello, World!";
    }
};
//usage
HelloWorld helloworld(new LanguagePolicyA);
helloworld.run();

Functionality and level of abstraction wise I don't see much of a difference in the two approach (even though the second approach has few extra lines of code for LanguagePolicy, I think it is needed for the other users to know the interface; otherwise understanding LanguagePolicy depends upon the documentation). But I do think the later to be 'clean' (coming from someone who has not used template much). This is because personally in my opinion non-templated classes are cleaner to look at and understand. An extremely good example is the popular library VTK (Visualization Tool Kit) which solves many different problems using the second approach. Even though there are not extensive documentations of VTK, most of us - its users, can just have a look into its class diagrams (sometimes they are quite big) and deduce behaviors of classes; and develop highly configurable and complicated pipelines in our application (can't imaging VTK to be template based :)). The opposite is libraries like STL/BOOST which I don't think is possible for anyone to be able to identify the working of the classes without the use of extensive documentation.

So my question is, is the template based policy design really superior (only in this scenario of policy based design) than virtual inheritance based? If so, when and why?

krips89
  • 1,683
  • 4
  • 17
  • 32

2 Answers2

2

Both are valid ways of structuring, it actually depends on the requirements. E.g.

Runtime vs compile time polymorphism.

When do you want/can/have to achieve polymorphism ?

Performance overhead of virtual calls

Templates generate code that has no indirections

The actual usage of the class.

When you have to store heterogenous collections, a base class is needed, so you have to use inheritance.

A very good book on policy-based design (a bit dated but good nevertheless) is Modern C++ Design

Tasos Vogiatzoglou
  • 2,393
  • 12
  • 16
  • -> Template 'simulates' run time polymerphism by generating classes at compile time. So, why not use runtime directly? Why do we care? -> I will take a look, but how much is the overhead on virtual calls really? Are the significant enough to cause a effect? – krips89 Jun 02 '15 at 13:16
  • @krips89 The second point. There is a performance overhead with virtual calls, which may be important in some cases. – Tasos Vogiatzoglou Jun 02 '15 at 13:18
  • 1
    @krips89 It depends but if you take into consideration the indirection, the mess with the cache lines, the possibility of a templated function to be inlined, there can be a gain from using policies. – Tasos Vogiatzoglou Jun 02 '15 at 13:20
  • Yes I am reading that book only; but he claimed the templated based approach to be best of all design which I could not get any evidence to back up. He did discuss about the advantages and disadvantages of most of the approaches (a lot of disadvantages on templates) but kept on pushing on templated implementation. – krips89 Jun 02 '15 at 13:32
  • @krips89 Alexandrescu is really good at what he does but at the end of the day there are arguments for/against both ways. These are tools that should be applied to solve a problem. Sometimes the problem calls for inheritance, sometimes for policy-based design. – Tasos Vogiatzoglou Jun 02 '15 at 13:36
  • 1
    @krips89 A quick benchmark (I was wondering for the actual differences) https://ideone.com/LIpkqC – Tasos Vogiatzoglou Jun 02 '15 at 14:24
  • wow thats quite a lot of difference (over 10k iteration though). Was not expecting this much. Even with this difference, I'm wondering if it would be wise to sacrifice design over performance. I am confused now, as I almost had made up mind for inheritance based design; but my application really needs to be inclined towards performance (a computer vision object detection library) – krips89 Jun 02 '15 at 15:10
  • @krips89 Take it with a grain of salt but yes, there seem to be a big difference – Tasos Vogiatzoglou Jun 02 '15 at 15:13
  • @krips89 Personally, I don't think you're sacrificing design at all when choosing the template version. It's a different design, maybe a little less familiar to some, but in my opinion in no way inferior to the inheritance based design. – JorenHeit Jun 02 '15 at 18:02
  • @TasosVogiatzoglou I wonder if it's aggressive compiler optimisations. After i added volatile to `a` and `b`, difference is not a lot. https://ideone.com/ESGeU0 Also, here's for some fun : https://quick-bench.com/q/zfs1bunwOPqIb2_Dk4nHdXd5_Yo spoliers: equal! – puio Jan 03 '21 at 17:58
1

Depends on the situation I guess... A possible downside of using templates is that the type should be known at compile-time:

HelloWorld<English> hw; // English is plugged at compile-time

In your second example, where you're using a pointer-to-base, this pointer might point to a variety of derived classes. What exactly it points to is not required to be known at compile-time and can therefore be determined by (user-)input at runtime. A possible down-side of this approach is virtual call overhead. In some applications, and on some platforms, this might be unwanted.

JorenHeit
  • 3,877
  • 2
  • 22
  • 28
  • Yes; so as far as I understood till now, the only problem which shows up in the second approach is the 'virtual call overhead'. If I look purely in the design perspective (without caring about the implementation overhead) the second approach comes out to be superior. – krips89 Jun 02 '15 at 13:22
  • That's the only downside I can think of right now. On top of that, abstract bases help forcing an interface on derived classes, which is nice. Static interface-checking will probably become available in C++17 when Concepts are added to the language though (awesome). – JorenHeit Jun 02 '15 at 13:52