Compile-time polymorphism !!

jeyanthan

Srijeyanthan

Posted on February 22, 2020

Compile-time polymorphism !!

Curiously recurring template pattern is one of the rarely used design patterns in general programming, normally this is referred to as CRTP. We all are well familiar with dynamic polymorphism implementation in C++, and how it compiler handles dynamic features using virtual functions.

Alt Text

The above diagram show, how B and C have their own implementation of the write method, it is very straightforward. Once your program compiled, compiler basically creates VPtr table(virtual pointer table) and stores the addresses of virtual methods in that table. Once the Virtual Table is created, it is shared across all the instances of the class.

The compiler only creates one single instance of VTable to be shared across all the objects of a class. Every instance of the class B or C has its own version of VPtr.

Normally, compiler adding 4 bytes for VPtr and If we print the size of a class object containing at least one virtual method, the output will be sizeof(class data) + sizeof(VPtr).

So, what is the issue here? well, if you are working on a high throughput system where every single function call is matters, and collectively delaying the overall process. If your program heavily implementing a virtual function, then frequently calling this writing method in the above example ends up in frequent lookup of VTable.

Now let's jump into compile-time polymorphism where bindings happen during compile time.

template <class T>
class Writer
{
  public:
    Writer()  { }
    ~Writer()  { }

    // Look at this declaration
    void write(const char* str) const
    {
      static_cast<const T*>(this)->writeImpl(str); 
    }
};

class FileWriter : public Writer<FileWriter>
{
  public:
    FileWriter(FILE* aFile) { mFile = aFile; }
    ~FileWriter() { fclose(mFile); }

    //here comes the implementation of the write method on the subclass
    void writeImpl(const char* str) const
    {
       fprintf(mFile, "%s\n", str);
    }

  private:
    FILE* mFile;
};


class ConsoleWriter : public Writer<ConsoleWriter>
{
  public:
    ConsoleWriter() { }
    ~ConsoleWriter() { }

    void writeImpl(const char* str) const
    {
      printf("%s\n", str);
    }
};


// Driver code 
int main() 
{ 
    // An Writer type pointer pointing to FileWriter 
    Writer<FileWriter>* pWriter = new FileWriter; 


    pWriter->write("Hi I am faster"); 



    return 0; 
} 

Now, the compiler won't allocate that 4-byte extra memory to hold VPtr, and it will execute really faster during the high-frequency function calls. Please note that CRTP won't really fit in all the use cases, the developer should decide the places where it can fit to reduce the overhead of VTable lookup.

💖 💪 🙅 🚩
jeyanthan
Srijeyanthan

Posted on February 22, 2020

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related

Compile-time polymorphism !!
cplus Compile-time polymorphism !!

February 22, 2020