c++ templates gcc

c++ - Especialización explícita en el ámbito del espacio de nombres



templates gcc (5)

Aún mejor: puede combinar especialización parcial con argumentos de plantilla predeterminados. De esta forma, la modificación del código de VC ++ es menor, ya que no es necesario modificar las llamadas a la función especializada.

template <typename TL, class Dummy=int> void Verify(int position, int constraints[]) { } template <class Dummy=int> void Verify<int, Dummy>(int, int[]) { }

template<typename T> class CConstraint { public: CConstraint() { } virtual ~CConstraint() { } template <typename TL> void Verify(int position, int constraints[]) { } template <> void Verify<int>(int, int[]) { } };

Compilar esto bajo g ++ da el siguiente error:

Especialización explícita en el ámbito del espacio de nombres ''clase CConstraint''

En VC, compila bien. ¿Puede alguien decirme la solución?


Es posible que no pueda especializar explícitamente la plantilla de miembro, pero puede especializarla parcialmente . Si agrega un segundo parámetro "int dummyParam" y también lo agrega a la especialización, debería funcionar con ambos compiladores.

No es que yo supiera esto hace más de 10 segundos, pero buscando en Google el mismo error, encontré este enlace y funcionó para la especialización de mi plantilla de miembro.


Otra forma de resolverlo es delegando en una función privada y sobrecargando esa función. De esta forma, todavía tiene acceso a los datos de miembro de *this y al tipo de parámetro de plantilla externo.

template<typename T> struct identity { typedef T type; }; template<typename T> class CConstraint { public: template <typename TL> void Verify(int position, int constraints[]) { Verify(position, constraints, identity<TL>()); } private: template<typename TL> void Verify(int, int[], identity<TL>) { } void Verify(int, int[], identity<int>) { } };


Solo tome la especialización de plantilla fuera de la declaración de clase. gcc no permite la especialización de plantilla en línea.

Como otra opción, simplemente eliminar la plantilla de línea <> parece funcionar para mí.


VC ++ no es compatible en este caso: las especializaciones explícitas deben estar en el ámbito del espacio de nombres. C ++ 03, §14.7.3 / 2 :

Se debe declarar una especialización explícita en el espacio de nombres del cual la plantilla es miembro, o, para las plantillas de miembros, en el espacio de nombres del cual la clase adjunta o la plantilla de clase adjunta es un miembro.
Se debe declarar una especialización explícita de una función miembro, clase miembro o miembro de datos estáticos de una plantilla de clase en el espacio de nombres del que la plantilla de clase es miembro.

Además, tiene el problema de que no puede especializar las funciones miembro sin especializar explícitamente la clase contenedora debido a C ++ 03, §14.7.3 / 3 , por lo que una solución sería permitir que Verify() reenvíe a un servicio posiblemente especializado. función libre:

namespace detail { template <typename TL> void Verify (int, int[]) {} template <> void Verify<int>(int, int[]) {} } template<typename T> class CConstraint { // ... template <typename TL> void Verify(int position, int constraints[]) { detail::Verify<TL>(position, constraints); } };