Cuando especializo una función/constante de miembro (estática) en una clase de plantilla, no estoy seguro de a dónde debe ir la declaración.Declaración de especialización de miembro de clase de plantilla
He aquí un ejemplo de lo que lo haga - yoinked directamente de IBM's reference on template specialization:
=== IBM miembro especialización Ejemplo ===
template<class T> class X {
public:
static T v;
static void f(T);
};
template<class T> T X<T>::v = 0;
template<class T> void X<T>::f(T arg) { v = arg; }
template<> char* X<char*>::v = "Hello";
template<> void X<float>::f(float arg) { v = arg * 2; }
int main() {
X<char*> a, b;
X<float> c;
c.f(10); // X<float>::v now set to 20
}
La pregunta es, ¿cómo puedo dividirlo en archivos de cabecera/cpp? La implementación genérica está obviamente en el encabezado, pero ¿qué pasa con la especialización?
No puede ir en el archivo de encabezado, porque es concreto, lo que lleva a una definición múltiple. Pero si entra en el archivo .cpp, ¿está el código que llama a X :: f() al tanto de la especialización, o podría depender del genérico X :: f()?
Hasta ahora tengo la especialización en el .cpp solamente, sin declaración en el encabezado. No tengo problemas para compilar o incluso ejecutar mi código (en gcc, no recuerdo la versión en este momento), y se comporta como se esperaba, reconociendo la especialización. Pero A) No estoy seguro de que esto sea correcto, y me gustaría saber qué es, y B) mi documentación de Doxygen sale poco clara y muy engañosa (más sobre eso en
un momento
una pregunta posterior).
Lo que parece más natural para mí sería algo como esto, declarando la especialización en la cabecera y definirlo en el .cpp:
=== === XClass.hpp
#ifndef XCLASS_HPP
#define XCLASS_HPP
template<class T> class X {
public:
static T v;
static void f(T);
};
template<class T> T X<T>::v = 0;
template<class T> void X<T>::f(T arg) { v = arg; }
/* declaration of specialized functions */
template<> char* X<char*>::v;
template<> void X<float>::f(float arg);
#endif
=== XClass.cpp ===
#include <XClass.hpp>
/* concrete implementation of specialized functions */
template<> char* X<char*>::v = "Hello";
template<> void X<float>::f(float arg) { v = arg * 2; }
... pero no tengo idea si esto es correcto. ¿Algunas ideas?
Pregunta, por curiosidad: ¿por qué la preferencia por la inclusión? Parece un "requisito" extraño de imponer: que "por defecto" una especialización de plantilla estaría en línea. Pregunto todo esto solo porque insinúas que eso es lo que "normalmente" harías, y no veo por qué normalmente querría hacer eso más de lo que quisiera declarar cualquier otra función en línea. – Ziv
Se trata de la preferencia de ponerlos en encabezados, 'inline' es un efecto secundario. Menos para escribir, más oportunidades de optimización, sin errores al olvidar una declaración. También siempre necesita especializarse completamente y para la mayoría de las plantillas eso significaría agregar una declaración e instanciación explícita para cada combinación de tipos con los que se usa. Tipo de derrota el intento de genericidad, ¿no? –
Bueno, por supuesto, solo estoy hablando de casos en los que una especialización completa es lo que se desea, de lo contrario obviamente es una historia completamente diferente ... Da la vuelta a la pregunta, entonces: ¿por qué esas mismas ventajas no nos llevan a preferir generalmente? escribe todas las funciones en línea? – Ziv