Come ottenere un oggetto di una classe sconosciuta con data nomeclasse
-
20-09-2019 - |
Domanda
Sto cercando un modo per determinare in fase di esecuzione, quale tipo di oggetto deve essere alloced (basata su un determinato nome di classe, che è di tipo const char*
).
Bene il modo più semplice, naturalmente, è quello di utilizzare i carichi di if
s / else if
s, ma quello non sembra applicabile, perché ho> 100 classi diverse (bene almeno derivano tutte da una classe di base), e devo aggiungere nuovi classi abbastanza regolarmente pure.
I già si avvicinò con una prima bozza, ma purtroppo doesnt compilo ancora (mingw & g ++ 4.4)
template<typename TBase, typename TDerived, typename... TArgs>
Base* get_classobject(const char* classname)
{
if(strcmp(classname,typeid(TDerived).name())==0)
return new TDerived; //
else if(sizeof...(TArgs)>0)
return get_classobject<TBase,TArgs...>(classname);
else
return 0;
}
int main()
{
Base* obj = get_classobject<Base,A,Foo,B,C>("Foo");
// ^- Types A B C and Foo are all derived from Base
delete obj; //of course we got an virtual dtor ;)
return 0;
}
, ma che pretende molto sizeof...(TArgs)>0
fermata gcc dal tentativo di generare il codice per get_classobject<TBase,const char*>(const char*)
che non riesce
Avete qualche idea, come riparare questo, o qualsiasi altra idea? Grazie.
EDIT: ho risolto:
template<typename TBase, typename TDerived>
Base* get_classobject(const char* classname)
{
if(strcmp(classname,typeid(TDerived).name())==0)
return new TDerived;
return 0;
}
template<typename TBase, typename TDerived, typename TArg, typename... TArgs>
Base* get_classobject(const char* classname)
{
if(strcmp(classname,typeid(TDerived).name())==0)
return new TDerived;
return get_classobject<TBase,TArg,TArgs...>(classname);
}
EDIT Per i lettori interessati:
Si dovrebbe ora che l'attuazione di cui sopra non è compilatore indipendente a tutti.
L'uscita di typeif(sometype).name()
è compilatore / implementazione specifica.
Utilizzando una variabile static const char* name
o funzione all'interno di tutte le classi derivate, sarebbe risolvere questo problema, ma aggiunge un po 'di lavoro (naturalmente è possibile utilizzare una macro per questo, ma se si utilizza già le macro, si potrebbe partecipavano utilizzare un altro metodo oggetto di fabbrica)
Soluzione
Non si può semplicemente dichiarare
template<typename TBase, typename TDerived, typename TArg, typename... TArgs>
Quindi è possibile specializzarsi per il caso di
typename TBase, typename TDerived, typename TArg
Altri suggerimenti
Leggi le risposte oltre qui , probabilmente bisogno di una fabbrica.
Che ne dite di fare un get_classobject specializzata () senza temlates variadic? Che sarebbe fermare la ricorsione.
Si potrebbe quindi avere una definizione con la mascherina variadic, e un altro di appena template<typename TBase, typename TDerived>
. Un'altra idea è quella di fare un sovraccarico di non-modello che accetta solo const char *, e restituisce 0.
Questo suona come si sta cercando per il modello oggetto factory classica. Date un'occhiata a questo StackOverflow domanda . Personalmente mi piace questo metodo