2012-04-09 10 views
10

Como parte de una clase de rasgos para un programa más grande, intenté crear una variable de clase estática que podría tener un valor diferente según el tipo con el que se creaba la instancia de la plantilla de clase adjunta.Compilador G ++ ¿Error o código defectuoso? : "definición de plantilla de no plantilla"

He simplificado el código correspondiente para llegar a un ejemplo escueto de lo que estoy hablando:

#include <iostream> 
#include <string> 
#include <type_traits> 

template <class T, class Enable = void> 
struct Foo; 

template <class T> 
struct Foo<T, 
    typename std::enable_if<std::is_integral<T>::value>::type 
> 
{ 
    static std::string message; 
}; 

template <class T> 
struct Foo<T, 
    typename std::enable_if<std::is_floating_point<T>::value>::type 
> 
{ 
    static std::string message; 
}; 

template <class T, class Enable> 
std::string Foo<T, Enable>::message; 

con GCC 4.6, esto da un error del compilador: template definition of non-template ‘std::string Foo<T, Enable>::message. El problema ocurre debido a las dos últimas líneas, donde solo estoy definiendo la variable estática std::string Foo<T, Enable>::message.

Estoy confundido por qué está sucediendo esto. El error del compilador desaparece si omito las últimas dos líneas (pero, por supuesto, eso causa errores del enlazador.) ¿Es esto un error del compilador con GCC?

+2

+1 para "un ejemplo escueto". http://sscce.org/. –

+0

Necesita incluir

+0

@Vaughn, ese no es el problema aquí, pero actualicé el fragmento de código. – Channel72

Respuesta

10

Esto sólo funciona cuando los parámetros de plantilla coincide con la especialización parcial:

template <class T> 
std::string Foo<T, 
    typename std::enable_if<std::is_integral<T>::value>::type 
>::message; 

template <class T> 
std::string Foo<T, 
    typename std::enable_if<std::is_floating_point<T>::value>::type 
>::message; 

Esto se especifica en la sección 14.5.4.3 de la norma C++ 03. La idea es que una especialización parcial es una nueva plantilla y los parámetros de la plantilla de los miembros que se definen externamente tienen que coincidir con los parámetros de la plantilla de la definición de clase para que sepa a qué plantilla va el miembro.

En su ejemplo, la regla evita definir el miembro del mensaje para los tipos que no son integrales o coma flotante.

+0

¿Por qué solo funciona en ese caso? – SirGuy

+0

¿Hay alguna razón por la cual una definición única no funciona aquí? ¿Es esto algo obligatorio según el estándar de C++, o una peculiaridad en G ++? – Channel72

+0

@GuyGreer: Supongo que porque el campo static _message_ no está declarado para la plantilla general (solo para algunas especializaciones). es imposible definir algo que no está declarado – user396672

Cuestiones relacionadas