template c++ static templates initialization specialization

c++ - template - class specialization



Inicialización estática de miembros para la clase de plantilla especializada. (3)

class A { }; template <typename A, int S> class B { public: static int a[S]; B() { a[0] = 0; } }; template<> int B<A, 1>::a[1]; int main() { B<A, 1> t; t; }

Se compila bajo GCC 4.1, pero no enlaza:

static.cpp:(.text._ZN1BI1ALi1EEC1Ev[B<A, 1>::B()]+0x5): undefined reference to `B<A, 1>::a''

Preferiría mantener la inicialización especializada si es posible, ya que la matriz contiene algunos datos específicos del tipo.


Necesitas realmente asignarle un valor.

template<> int B<A, 1>::a[1] = {0};


No se vincula porque no define un valor para su miembro estático.

template<> int B<A, 1>::a[] = { 0 };

Editar:

Por cierto: siempre preferiría boost :: array en lugar de los tipos C nativos:

class A { }; template <typename A, std::size_t S> class B { public: static boost::array<int, S> a; B() { a[0] = 0; } }; template<> boost::array<int, 1> B<A, 1>::a = { }; int main() { B<A, 1> t; cout << t.a[0] << endl; }


Para las especializaciones estáticas de miembros, si no inicializa el miembro, se toma como una declaración de especialización, que simplemente dice "Oh, no ejemplifique al miembro desde la plantilla principal, porque hay una definición especializada en otro lugar". Debe mencionarse que la definición debería aparecer en un archivo .cpp (de lo contrario, ganará lo contrario: múltiples definiciones), y la declaración sin inicializador aún se debe colocar en el archivo de encabezado.

Ahora, la sintaxis correcta es la siguiente, y no debería aparecer en un archivo de encabezado, sino en un archivo .cpp

template<> int B<A, 1>::a[1] = { };

Lo siguiente debería seguir apareciendo en un archivo de encabezado:

template<> int B<A, 1>::a[1];

Esto servirá como la declaración de especialización.

De esto, se deduce que no puede especializar a un miembro que solo tiene un constructor predeterminado y no se puede copiar, porque necesitaría esta sintaxis:

// needs a copy constructor! template<> Type Class<Arguments>::member = Type();

C ++ 0x arregla esto:

// doesn''t anymore need a copy constructor template<> Type Class<Arguments>::member{};

Para las personas de Standardese entre nosotros, aquí están las citas:

14.7.3/6 :

Si una plantilla, una plantilla miembro o el miembro de una plantilla de clase está explícitamente especializada, dicha especialización se declarará antes del primer uso de esa especialización que causaría una instanciación implícita, en cada unidad de traducción en la que se produzca dicho uso. ; no se requiere diagnóstico

14.7.3/15 :

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: no hay sintaxis para la definición de un miembro de datos estáticos de una plantilla que requiere inicialización predeterminada.

template<> X Q<int>::x;

Esta es una declaración independientemente de si X puede inicializarse por defecto (8.5). ]

3.2/3 :

Cada programa contendrá exactamente una definición de cada función u objeto no en línea que se utiliza en ese programa; No se requiere diagnóstico.

3.2/5 :

Puede haber más de una definición de un tipo de clase (cláusula 9), tipo de enumeración (7.2), función en línea con enlace externo (7.1.2), plantilla de clase (cláusula 14), plantilla de función no estática (14.5.5) , miembro de datos estáticos de una plantilla de clase (14.5.1.3), función miembro de una plantilla de clase (14.5.1.1) o especialización de plantilla para la cual no se especifican algunos parámetros de plantilla (14.7, 14.5.4) en un programa [.. .]

La restricción de esto a "para los que no se especifican algunos parámetros de la plantilla" significa que se nos permite hacer lo siguiente, ubicándolo en un encabezado (por lo tanto, posiblemente tenga múltiples definiciones de esta especialización):

template<> template<typename T> Type OuterClass<int>::InnerClass<T>::StaticMember = 0;

En su caso, tiene todos los parámetros especificados, por lo que no está cubierto por la regla de una definición para permitir varias definiciones.