C++ Template Idioms in Application Design

Goal

To analyse how C++ template feature is being used effectively along with inheritance in many successful frameworks and libraries inspite of its complexity and drawbacks.

Currently we have number of libraries and frameworks that use template based design
1.      Standard Template Library
2.      Active Template Library
3.      Windows Template Library
4.      Boost Library
5.      Adaptive Communication Environment
6.      MFC template-based collection classes
7.      OLEDB Templates
8.      Generic data structures and algorithms in libraries like Qt.
9.      Many open source logging, game engines, and domain specific frameworks.

Why many times templates are preferred over inheritance + virtual functions though template feature has drawbacks?

How templates can be used effectively to implement object oriented design patterns for any applications extensible white box frameworks? 




Dynamic Polymorphism Vs Static Polymorphism






 

Above example can be designed both using both inheritance(run-time polymorphism) or templates (static polymorphism).

Object Model for runtime polymorphism





Inheritance version classes declaration:
class AnthraxInfectedMessage
{
public:
      virtual void FormatAndSendMessage(string msg);
};
class AnthraxInfecetedEmail : public AnthraxInfectedMessage
{
public:
      void FormatAndSendMessage(string msg);
};
class AnthraxInfectedFax : public AnthraxInfectedMessage
{
Public:
     void FormatAndSendMessage(string msg);
};

Application high level logic might use above classes as follows:-
AnthraxInfectedMessage* m_ptrMsg;
…..
m_ptrMsg = new AnthraxInfecetedEmail(msg);
…..
m_ptrMsg->FormatAndSendMessage(msg);
Object Model for static polymorphism

 Template version classes declaration[ just an outline ]:

template <typename T>
class AnthraxInfectedMessage
{
       T* m_pMethodOfComm;
public:
      void SetManager(T* ptrMgr)
      {
             m_pMethodOfComm = ptrMgr;
      }
       void FormatAndSendMessage()
        {
                m_pMethodOfComm->FormatMsg(msg);
                m_pMethodOfComm->Send(msg);
        }
};
Application high level logic might use the template as follows:-
 
EmailManager* m_ptrMgr = new EmailManager(msg);
AnthraxInfectedMessage<EmailManager*> m_ptrMsg;
m_ptrMsg.SetManager(m_ptrMgr);
m_ptrMsg.FormatAndSendMessage();


Important points



  • Polymorphism means many forms
  • There are two types of polymorphisms:-
     o   Runtime polymorphism/dynamic polymorphism
o   Compile time polymorphism/static polymorphism
  • Runtime polymorphism is based on virtual functions and inheritance.
  • Compile time polymorphism is based on templates.
  • Templates are not restricted for polymorphism of type alone; they can be used for polymorphism of  behaviour.
  • Template version of code is much faster than virtual method equivalent.
  • Virtual method version is not type safe; template method is type-safe.
  • Templates and inheritance can be combined sometimes. Idioms like “Curiously Recurring Template” will be discussed in detail in coming sections.
  • Policy-based design and extensible white-box frameworks can be implemented using C++ templates. Template meta programming, traits and filters in templates, implementation of “template method pattern”, strategy pattern etc will be discussed in detail in coming sections.

Using templates instead of virtual functions


classes declaration:


class FriedRice;
class ChowMein;
template <class T>
class FriedRice : ChineseFastFood<FriedRice>
{
public:
 void InitialCook();
 void PrepareSeasonedMixture();
 void PrepareFryPan();
 void AddSpices();
 void AddChicken();
 void AddMainItem();
 void StirAndFry();
 void DishOut();
};
template <class T>
class ChineseFastFood
{
public:
 void implementReciepe()
 {
  static_cast<T*>(this)->InitialCook();
  static_cast<T*>(this)->PrepareSeasonedMixture();
  static_cast<T*>(this)->PrepareFryPan();
  ....
 }
};
 
 
//Probable Usage
FriedRice fRice;
fRice.implementReciepe();


  • Using templates, virtuality  of a member function can be parameterized.
  • Additional amount of flexibility is afforded to static polymorphism using the inheritance.
  • This pattern is also called curiously recurring template pattern.
  • Using template allows to seperate the high level logic implementation from granular sub tasks implementation.
  • Save space by avoiding VTABLE and Virtual Pointers.
  • Improves perfomance by avoiding two levels of runtime indirection ( Virtual function pointer + Virtual function table )
  • Base class doesn't actually need to define the method - like a pure virtual function.
  • Can call static methods and public members.

No comments:

Post a Comment