2010-09-08 7 views
6

Estoy intentando averiguar por qué este ejemplo no se compila. Según tengo entendido, si una variable estática no se establece explícitamente, se establece de manera predeterminada en 0. En los cinco ejemplos siguientes, cuatro de ellos se comportan como era de esperar, pero el que está comentado no se compilará.Inicializando miembros estáticos de una clase con plantilla

#include <iostream> 
class Foo 
{ 
public: 
    static int i; 
    static int j; 
}; 
template <int n> 
class Bar 
{ 
public: 
    Bar(int) { } 
    static int i; 
}; 

static int i; 
int Foo::i; 
int Foo::j = 1; 
template <> int Bar<2>::i; 
template <> int Bar<3>::i = 3; 

int main(int argc, char** argv) 
{ 
    std::cout << "i   " << i << std::endl; 
    std::cout << "Foo::i " << Foo::i << std::endl; 
    std::cout << "Foo::j " << Foo::j << std::endl; 
    //std::cout << "Bar<2>::i " << Bar<2>::i << std::endl; // Doesn't compile? 
    std::cout << "Bar<3>::i " << Bar<3>::i << std::endl; 
    return 0; 
} 

¿Por qué no int Bar<2>::i hacer lo mismo que int Foo::i o static int i?

Editar: Había olvidado agregar la plantilla <> a la barra < 2> y la barra < 3> declaraciones. (No soluciona el problema, sin embargo, sigue recibiendo errores de enlace)

+3

Duplicado de [inicialización de miembro estático para la clase de plantilla especializada] (http://stackoverflow.com/questions/2342550/static-member-initialization-for-specialized-template-class) –

+0

¿cuál es el error de enlace? – Chubsdad

+0

@Chubsdad: Sin dudas, es "Referencia indefinida a' Bar <2> :: i' "o algo así. En el código del OP, 'template <> int Bar <2> :: i;' es una declaración _nondefining_ (vea el duplicado vinculado para la explicación detallada de litb). –

Respuesta

5

Según las normas del estándar actual de C++, la especialización template <> int Bar<2>::i; es solo una declaración y nunca una definición. Para convertirse en una definición, debe especificar un inicializador. (Véase la cláusula 14.7.3/15)

Aparte de eso, que faltaban un caso muy común: la definición de un miembro estático no especializado, de una plantilla:

template <int n> int Bar<n>::i; 

Esto proporciona una definición para Bar<N>::i para N no igual a 2 o 3.

1

De acuerdo con el último borrador de estándar de C++ que dice

14.7.3/13 Una especialización explícita de un miembro de datos estáticos de una plantilla es una definición si la declaración incluye un inicializador; de lo contrario, es una declaración.
[Nota: la definición de un miembro de datos estáticos de una plantilla que requiere la inicialización por defecto debe utilizar un-init-lista arriostrados:

template<> X Q<int>::x;  //declaration 
template<> X Q<int>::x(); // error: declares a function 
template<> X Q<int>::x { }; // definition 

- nota final]

Así que lo que están pidiendo es posible , si tu compilador lo está soportando.

Cuestiones relacionadas