Friday, January 8, 2016

Practical CRTP (or lack thereof)

I have recently performed an experiment where I took the Loginator code and removed all dynamic polymorphism in place of static polymorphism. The motivation was the fact that since the sensors were all hard-wired to the board, all references to them could be figured at compile-time, and static polymorphism plus the optimizer and inliner could make "better" code. I also had an irrational fear of the vtables being corrupted.

Having gone through this exercise, I think I can say that CRTP is not the right way to do static polymorphism. It works, but it is ugly and infectious. If a class uses an object which is defined with CRTP, that class itself must also be made to use CRTP. I don't know if the machine code produced is faster, but I do know that it is significantly larger.

The motivation for changing back is the hardware description block which I am adding to the Loginator code, in hopes of being able to unify the Logomatic, Loginator, Rocketometer, Rollercoasterometer, and Pocketometer. My idea is to be able to load the same binary image into any LPC2148 based hardware I have or make, and have the software read the hardware description block to see what hardware it is attached to. This is all done at runtime, so we need dynamic polymorphism again.

CRTP isn't all bad. It works fine for instance in the dump class, where you can use it to make specializations of dump which are resolved at compile time. The problem arises when you want to pass a CRTP object as a parameter. At that point, the reference or pointer to the object has to be CRTP also, which frequently causes the whole class to need to be CRTP.

The idea then is that the general-purpose drivers are built into the code, and constructed at runtime from the hardware description block.