Ecco un esempio minimo:inizializzazione di un membro statico all'interno di un modello di
#include <iostream>
struct B {
B() { x = 42; }
static int x;
};
int B::x;
template <int N>
struct A {
int foo() { return b.x; }
static B b;
};
template<int N>
B A<N>::b;
//template struct A<2>; // explicit instantiation with N = 2 (!)
int main(int argc, char **argv) {
std::cout << A<1>().foo() << std::endl;
return 0;
}
Questo programma scrive 42 con g ++ 4.9.2, ma scrive 0 utilizzando Visual Studio 2015 RC. Inoltre, se disattengo l'istanziazione esplicita, VS2015RC fornisce anche 42, il che è piuttosto interessante, poiché il parametro template qui è diverso da quello utilizzato nella funzione main
.
È un bug? Suppongo che g ++ sia corretto, in quanto esiste un riferimento aall'interno di foo
, pertanto è necessario chiamare il costruttore di B
.
EDIT: C'è una soluzione semplice - se c'è una variabile non statico in B
, a cui fa riferimento A
, VS2015RC compilerà correttamente:
// ...
struct B {
B() { x = 42; }
static int x;
int y; // <- non-static variable
};
// ...
template <int N>
struct A {
int foo() { b.y; return b.x; } // <- reference to b.y
static B b;
};
Questo sembra funzionare, anche sebbene b.y
, come una dichiarazione, è ovviamente NOP.
possibilmente correlati: http://stackoverflow.com/questions/3035422/static-initialization-order-fiasco – NathanOliver