Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Policy based design and best practices - C++

struct InkPen {   void Write()   {     this->WriteImplementation();   }    void WriteImplementation()   {     std::cout << "Writing using a inkpen" << std::endl;   }  };  struct BoldPen {   void Write()   {     std::cout << "Writing using a boldpen" << std::endl;   } };  template<class PenType> class Writer : public PenType { public:   void StartWriting()   {     PenType::Write();   } };  int main() {   Writer<InkPen> writer;   writer.StartWriting();   Writer<BoldPen> writer1;   writer1.StartWriting();   return 0; } 

I wrote the above code as part of learning policy based designs. I have few questions on the above code

1 - Does this implementation look correct? I mean: does it really look like a policy based design?

2 - I can now hook any kind of pens to writer. But what will I do when I got a pen with no default constructor (only parameterized constructors)? How will I handle this situation?

template<class PenType> class Writer : public PenType { public:   void StartWriting()   {     PenType::Write();   } }; 

3 - When the above code is used like

Writer<InkPen> writer; 

I guess compiler will replace PenType with InkPen. If yes, why I am not able to call just Write() from StartWriting() instead of prefixing base class name (PenType::Write())?

4 - I think policy based design forces you to derive from classes which is semantically invalid. In the above code, a writer is derived from a pen only because writer uses a pen. But saying writer is a pen is semantically invalid. Is there any other better way to address this or I am missing something here?

Any thoughts?

like image 216
Navaneeth K N Avatar asked May 16 '09 15:05

Navaneeth K N


People also ask

What is policy based class design?

Policy-based design. Policy-based design, also known as policy-based class design or policy-based programming, is the term used in Modern C++ Design for a design approach based on an idiom for C++ known as policies.

What is a policy in C++?

A policy is a class or class template that defines an interface as a service to other classes. Traits define type interfaces, and policies define function interfaces, so they are closely related. Sometimes, a single class template implements traits and policies.

Is Modern C++ Design still relevant?

Modern C++ Designis an important book. Fundamentally, it demonstrates 'generic patterns' or 'pattern templates' as a powerful new way of creating extensible designs in C++–a new way to combine templates and patterns that you may never have dreamt was possible, but is.

What is policy class?

Policy Classes A policy class is a template parameter used to transmit behavior. An example from the standard library is std::allocator , which supplies memory management behaviors to standard containers. Policy classes have been explored in detail by Andrei Alexandrescu in this chapter of his book, Modern C++ Design.


2 Answers

Here's how I would implement the class:

template<class PenType> class Writer { public:   Writer(const PenType& pen = PenType()) : pen(pen) {}    void StartWriting()   {     pen.Write();   }  private:   PenType pen; }; 

This allows the user to pass a specific Pen object to the constructor, if it either doesn't have a default constructor, or you don't want it to be used, and second, it still allows you to omit the PenType object if you're happy to let it create one with the default constructor. The C++ standard library does the same in many classes (think of the allocators for container classes for example).

I removed the inheritance. It didn't really seem to add anything (and might cause problems. You probably don't want the user of the Writer class to call the PenType::Write function directly. You could use private inheritance instead, but often, composition is a simpler and more conventional design.

In general, policy-based design does not require inheritance. Adding it as a member works just as well. If you do go for inheritance, make it private so you don't get the problem you mentioned as #4.

like image 136
jalf Avatar answered Oct 05 '22 22:10

jalf


This looks like a nice example of policy-based smart pointer implementation: link. Andrei Alexandrescu describes policy-based smart pointer implementation in one of his books. As to your questions now. I have some experience in this stuff but not enough to take my words for granted:

Ad 1 & 4. I guess policy-based design is more about templates than inheritance. You write a template class and template arguments are policy classes, like that:

template<class FooPolicy, class BarPolicy> class Baz {     // implementation goes here }; 

Then you use methods from policy classes in your class:

void Baz::someMethod(int someArg) {     FooPolicy::methodInit();     // some stuff     BarPolicy::methodDone(); } 

I use static methods in this example because often policy doesn't require any state. If it does, you incorporate policy's state by composition, not by inheritance:

template<class FooPolicy, class BarPolicy> class Baz {   private:     FooPolicy::State fooState; // might require 'typename' keyword, I didn't                                // actually tried this in any compiler     // rest of the Baz class }; 

Ad 2. You can write a template specialization - for a particular combination of main class and it's policies you can write a special version of any method or constructor, AFAIK:

template <> Baz<SomeConcreteFooPolicy, SomeConcreteBazPolicy>::Baz(someArgument)    : fooState(someArgument) {     // stuff here } 

Hope it helps you a bit,

Mike

like image 35
Jasiu Avatar answered Oct 05 '22 22:10

Jasiu