Automatic class registration in C++ is a common task, and a commonly asked question here on StackOverflow:
Register an object creator in object factory
Somehow register my classes in a list
automatic registration of object creator function with a macro
c++ automatic factory registration of derived types
The basic objective is to register classes automatically with some registry or factory so that it can do some work with each class later.
This is a well-established technique, used by libraries like (for example) Google Test (http://code.google.com/p/googletest), which automatically registers subclasses of the Test class so that each test can be instantiated automatically and run during test execution.
Registration can be accomplished by instantiating a static Registrar class whose constructor does the registration, or by clever use of the CRTP and putting the registration code in the base class constructor, or whatever you like (the links above offer several different possible techniques).
However, when I implement any of these techniques I find they scale very poorly. If I have 10,000 TEST macro invocations in Google Test, compilation and linking grind to a halt (MSVC 2010) and binary size explodes. If I implement this another way, using 10,000 subclasses with static registrars, I see the same behavior.
For instance, consider the simplified example:
#include <iostream>
#include <string>
class Base {
public:
Base( const std::string& Name_ ) : Name( Name_ ) { ; }
~Base() { ; }
virtual std::string GetName() const { return Name; }
virtual void DoSomething() = 0;
private:
std::string Name;
};
class Registry {
public:
static Registry& GetInstance() {
static Registry* Instance = new Registry();
return *Instance;
}
void Register( const Base* b ) {
std::cout << "Registered class " << b->GetName() << std::endl;
}
private:
Registry() { ; }
~Registry() { ; }
};
class Registrar {
public:
Registrar( const Base* b ) {
Registry::GetInstance().Register( b );
}
~Registrar() { }
};
#define REGISTER( CLASS ) \
class CLASS : public Base { \
public: \
CLASS( const std::string& Name ) : Base( Name ) { ; } \
virtual void DoSomething(); \
private: \
static Registrar m_Registrar; \
}; \
Registrar CLASS::m_Registrar( new CLASS( #CLASS ) ); \
void CLASS::DoSomething()
int main( int argc, char** argv )
{
return 0;
}
REGISTER( Class1 )
{
std::cout << "Doing something in Class1" << std::endl;
}
REGISTER( Class2 )
{
std::cout << "Doing something in Class2" << std::endl;
}
[...]
with a total of 10000 autogenerated REGISTER calls.
Is there a fundamental reason why this won't scale well? Will the compiler just choke on 10000 classes? Under MSVC 2010 compilation of the above takes almost two minutes on a fairly fast machine and produces a binary over 5 MB in size. If I do similar with Google Test I see the same result.
Writing Java code in C++ rarely works well. All those heap allocations are probably what's killing performance (as they would in Java, but Java startup is so slow that nobody would notice). Use static objects, and don't put a Registrar
object into each generated class; that's just a waste of time and space.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With