Come forzare l’inizializzazione di un membro statico?

Considera questo codice di esempio:

template char register_(){ return D::get_dummy(); // static function } template struct Foo{ static char const dummy; }; template char const Foo::dummy = register_(); struct Bar : Foo { static char const get_dummy() { return 42; } }; 

( Anche su Ideone .)

Mi aspetto che il dummy venga inizializzato non appena c’è un’istanza concreta di Foo , che ho con Bar . Questa domanda (e la citazione standard alla fine) ha spiegato abbastanza chiaramente, perché non sta succedendo.

[…] in particolare, l’inizializzazione (e tutti gli effetti collaterali associati) di un membro di dati statici non si verifica a meno che il membro di dati statici sia esso stesso utilizzato in un modo che richiede la definizione del membro di dati statici per esistere.

Esiste un modo per forzare l’ inizializzazione del dummy (efficacemente chiamando register_ ) senza alcuna istanza di Bar o Foo (nessuna istanza, quindi nessun trucco del costruttore) e senza l’utente di Foo bisogno di dichiarare esplicitamente il membro in qualche modo? Cookie extra per non aver bisogno della class derivata per fare qualsiasi cosa.


Modifica : trovato un modo con un impatto minimo sulla class derivata:

 struct Bar : Foo { // vvvvvvvvvvvv static char const get_dummy() { (void)dummy; return 42; } }; 

Però, mi piacerebbe che la class derivata non dovesse farlo. : |

Prendere in considerazione:

 template struct value { }; template struct HasStatics { static int a; // we force this to be initialized typedef value value_user; }; template int HasStatics::a = /* whatever side-effect you want */ 0; 

È anche ansible senza introdurre alcun membro:

 template struct var { enum { value }; }; typedef char user; template struct HasStatics { static int a; // we force this to be initialized static int b; // and this // hope you like the syntax! user :var::value, :var::value; }; template int HasStatics::a = /* whatever side-effect you want */ 0; template int HasStatics::b = /* whatever side-effect you want */ 0; 

Esiste un modo per forzare l’inizializzazione del dummy (efficacemente chiamando register_) senza alcuna istanza di Bar o Foo (nessuna istanza, quindi nessun trucco del costruttore)?

Non sarebbe sufficiente?

 std::cout << Foo::dummy; 

Mi viene in mente qualcosa del genere:

 // in some c++ file (to make i with internal linkage) static int i = init_dummy(Foo::dummy); 

dove init_dummy è definito in questo modo:

 int init_dummy(...) { return 1; } 

A causa della variabile args puoi inserire più inizializzazioni come:

 static int i = init_dummy(Foo::dummy, Foo::dummy, Foo::dummy); 

Come stai controllando il valore impostato da Bar. Ho cambiato il tuo codice e ho aggiunto un’altra funzione in barra come:

 .... static char const get_dummy(int){return Foo::dummy;} .... 

e mi sta dando esattamente il risultato atteso. Forse non sto capendo correttamente, cosa vuoi esattamente raggiungere?

I membri statici sono condivisi tra gli oggetti, pertanto il loro ambito deve essere risolto all’accesso. è per questo che usiamo :: dicendo esplicitamente al compilatore che questo è il membro della class a cui vogliamo accedere.