Working on KBoard I’ve been forced to face great number of design problems, which I’d say have all been solved quite neatly, with one big exception: the covariant argument problem, hereafter referred as CAP.
This dreaded problem manifests itself when trying to abstract a great amount of functionality from a system using a set of interfaces (i.e. abstract classes with only pure virtual functions) so that client code can add custom behaviour to the system by implementing all these interfaces.
Nothing new, you’d say, that’s exactly the purpose of abstract classes and interfaces, but the difference here is that we have a set of (possibly interdependent) interfaces that we would like to implement at once.
To better explain the situation, I need to set up some names, so suppose you have three interfaces IA, IB, IC, and two different and completely incompatible incarnations A, B, C and U, V, W. Suppose further that IA has a method
foo taking an IB as a parameter. When implementing the ABC incarnation in client code, you need to preserve the signature of
foo, so you’re forced to accept any IB as its parameter, while of course only B’s have a meaning there. This is the fundamental dilemma of CAP.
The story isn’t new: it’s been studied in great detail by type theorist and even addressed in real programming languages like Eiffel, but the subject is still somewhat controversial and I’m not sure that a clean solution really exists, even accepting a language switch (not that I would second it :)).
Our solution consists in a layer of ugly (and by ugly I mean very ugly) template code which does the work of type conversion and type checking that the compiler is unable to do. The strong point of this solution is that the client never needs to delve inside this messy kludge, and can simply implement the required functionality by creating classes complying to implicit interfaces.
If you are curious to understand how this really works, you can find a short description here, and obviously the code, which is only one header file (but ignore the comments, they’re ancient… yes, I know they should be kept up to date…).