Compile-time polymorphism !!
Srijeyanthan
Posted on February 22, 2020
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.
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.
Posted on February 22, 2020
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.