A colleague of mine told me about a little piece of design he has used with his team that sent my mind boiling. It's a kind of traits class that they can specialize in an extremely decoupled way.
I've had a hard time understanding how it could possibly work, and I am still unsure of the idea I have, so I thought I would ask for help here.
We are talking g++ here, specifically the versions 3.4.2 and 4.3.2 (it seems to work with both).
The idea is quite simple:
1- Define the interface
// interface.h
template <class T>
struct Interface
{
void foo(); // the method is not implemented, it could not work if it was
};
//
// I do not think it is necessary
// but they prefer free-standing methods with templates
// because of the automatic argument deduction
//
template <class T>
void foo(Interface<T>& interface) { interface.foo(); }
2- Define a class, and in the source file specialize the interface for this class (defining its methods)
// special.h
class Special {};
// special.cpp
#include "interface.h"
#include "special.h"
//
// Note that this specialization is not visible outside of this translation unit
//
template <>
struct Interface<Special>
{
void foo() { std::cout << "Special" << std::endl; }
};
3- To use, it's simple too:
// main.cpp
#include "interface.h"
class Special; // yes, it only costs a forward declaration
// which helps much in term of dependencies
int main(int argc, char* argv[])
{
Interface<Special> special;
foo(special);
return 0;
};
It's an undefined symbol if no translation unit defined a specialization of Interface
for Special
.
Now, I would have thought this would require the export
keyword, which to my knowledge has never been implemented in g++ (and only implemented once in a C++ compiler, with its authors advising anyone not to, given the time and effort it took them).
I suspect it's got something to do with the linker resolving the templates methods...
- Do you have ever met anything like this before ?
- Does it conform to the standard or do you think it's a fortunate coincidence it works ?
I must admit I am quite puzzled by the construct...