2011-05-20 12 views
20

Esto a VS2010sp1 no compila (que se compila con gcc 4.6 embargo):nombretipo fuera de plantilla

template<class T> 
struct Upcast; 

template<> 
struct Upcast<signed char> 
{ 
    typedef signed short type; 
}; 

template<> 
struct Upcast<char> 
{ 
    typedef typename std::conditional<std::is_signed<char>::value,short, unsigned short>::type type; 
}; 

int main() 
{ 
    Upcast<char>::type a; 
    return 0; 
} 

error de VS:

Error 1 error C2899: typename cannot be used outside a template declaration 

¿Qué equipo tiene la razón? VS o gcc?

Respuesta

26

VS está a la derecha en C++ 03. GCC tiene razón en C++ 0x.

Ahora puede ser sensato para GCC también para permitir este modo en C++ 03 (hay muchas cosas que los compiladores de verdad no se diagnostican en C++ 03 modo que en realidad son sólo válidas en C++ 0x), y también puede ser razonable que VS lo rechace en el modo C++ 03.

Ya no importa si un uso de typename QualifiedName ocurre o no en una plantilla, en C++ 0x. Es decir, el siguiente es perfectamente legal para C++ 0x:

#include<vector> 

int main() { 
    typename std::vector<int> v; 
} 

En C++ 03, typename sólo podía usarse dentro de una plantilla. Y la especialización explícita en su código no es una plantilla. No hay cláusulas template<typename T ...> (todos los parámetros en su código son correctos).

+0

¿Qué significa? – Nawaz

+0

GCC también proporciona el error al compilar sin '-std = C++ 0x'. – kennytm

+0

@KennyTM gracias, es bueno saberlo. ¿Qué versión de GCC usas? Tengo GCC4.6.0, que acepta mi muestra de código en el modo C++ 03 incluso con '-pedantic'. –

8

Según C++ 03, typename y template palabras clave no pueden en cualquier lugar fuera de una plantilla, incluyendo explícitas (completo) especializaciones de plantilla. Entonces MSVC++ es correcto según C++ 03

Según C++ 0x este código es correcto.

3

En este caso particular, parecería que VS2010 es correcto al rechazar el código:

14,6/5

La palabra clave nombretipo se aplicará sólo a los nombres calificados, pero esos nombres no tiene que ser dependiente. La palabra clave typename se usará solo en contextos en los que se puedan usar nombres dependientes. Esto incluye declaraciones y definiciones de plantilla, pero excluye declaraciones de especialización explícitas y declaraciones explícitas de creación de instancias.

Cuestiones relacionadas