Scalable automatic class registration in C ++

Automatically registering classes in C ++ is a common task, and the frequently asked question is here on StackOverflow:

Register the creator of the object in the factory object

Somehow register my classes in the list

automatic registration of the function of the creator of the object using a macro

C ++ automatic factory registration of derived types

The main task is to automatically register classes using some kind of registry or factory, in order to subsequently work with each class.

This is a well-established method used by libraries such as (for example, Google Test ( http://code.google.com/p/googletest ), which automatically registers subclasses of the Test class so that each test can be automatically created and run in test run time.

Registration can be done by creating an instance of the registrar's static class, whose constructor performs registration or skillfully uses CRTP and puts the registration code in the base class constructor or whatever (the links above offer several different possible methods).

However, when I implement any of these methods, I find that they scale very little. If I have 10,000 TEST macro requests in Google Test, compilation and linking breaks (MSVC 2010) and binary size explodes. If I implement this other way using 10,000 subclasses with static registrars, I see the same behavior.

For example, consider a 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; } [...] 

a total of 10,000 REGISTER calls triggered by auto-generation.

Is there a fundamental reason why this will not scale well? Will the compiler just choke on 10,000 classes? In MSVC 2010, the compilation above takes almost two minutes on a fairly fast machine and produces a binary size of more than 5 MB. If I quit Google Test, I see the same result.

+6
source share
1 answer

Writing Java code in C ++ rarely works well. All of these heap allocations are probably what kills performance (as in Java, but starting Java is so slow that no one has noticed). Use static objects and do not put the Registrar object in each generated class; it's just a waste of time and space.

+1
source

All Articles