Registrazione automatica di classe in C++ è un compito comune, e una domanda più frequenti qui su StackOverflow:scalabile registrazione della classe automatica in C++
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
L'obiettivo di base è registrare er classi automaticamente con qualche registro o fabbrica in modo che possa fare un po 'di lavoro con ogni classe più tardi.
Questa è una tecnica consolidata, utilizzata da librerie come (ad esempio) Google Test (http://code.google.com/p/googletest), che registra automaticamente sottoclassi della classe Test in modo che ogni test possa essere istanziato automaticamente ed essere eseguito durante l'esecuzione del test.
La registrazione può essere eseguita istanziando una classe di registrazione statica il cui costruttore esegue la registrazione, o mediante un uso intelligente del CRTP e inserendo il codice di registrazione nel costruttore della classe base o qualsiasi altra cosa desiderata (i collegamenti sopra riportati offrono diversi possibili tecniche).
Tuttavia, quando implemento una di queste tecniche, trovo che si ridimensiona molto male. Se in Google Test sono presenti 10.000 richiami di macro di TEST, la compilazione e il collegamento si arrestano (MSVC 2010) e le dimensioni binarie esplodono. Se implemento questo in un altro modo, usando 10.000 sottoclassi con registrar statici, vedo lo stesso comportamento.
Ad esempio, si consideri l'esempio semplificato:
#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;
}
[...]
con un totale di 10000 chiamate REGISTRO generati automaticamente.
Esiste un motivo fondamentale per cui questo non si adatta bene? Il compilatore si strozzerà solo su 10000 classi? Sotto MSVC 2010 la compilazione di quanto sopra richiede quasi due minuti su una macchina abbastanza veloce e produce un binario di dimensioni superiori a 5 MB. Se faccio lo stesso con Google Test, vedo lo stesso risultato.
Si prega di prestare attenzione alla differenza tra un 'class' e un' oggetto'. Questo codice ** non ** registra le classi (e non dovrebbe), registra ** oggetti **. –
Grazie Pete. Per il mio scopo, come per Google Test, ci sarà una mappatura uno-a-uno così posso scegliere una tecnica che registri entrambi, ma il tuo punto è ben preso. – DSII
No, senza un ** grande ** sforzo, non è possibile registrare le classi. –