... utilizado sin error de parámetros de plantilla

Necesito tu ayuda una vez más ...

Tenía el siguiente código, que estaba causando especialización explícita en el ámbito sin espacio de nombres error:

namespace __test
{
    template <int A, int B, typename C> class Test
    {
        template <int V> void check(C & a) { }
        template <> void check<0>(C & a) { } //error: explicit specialization in non-namespace scope 'class __test::Test<A, B, C>'
    };
}


Como ya sé cómo corregir este tipo de errores, definí la especialización fuera del alcance de la clase, sin embargo, obtuve otro error: ... usado sin parámetros de plantilla:

namespace __test
{
    template <> void Test::check<0>(C & a) { } //error: 'template<int A, int B, class C> class __test::Test' used without template parameters
}


Probablemente solo estoy siendo estúpido, pero no entiendo la causa de este problema y no sé cómo solucionarlo ... ¡Por favor ayuda!

preguntado el 10 de mayo de 11 a las 13:05

Su nombre __test es ilegal en el código escrito por el usuario. -

Gracias, fue lo primero que me vino a la mente cuando estaba simplificando el código problemático:

De MSVC, que logra compilar casi cualquier cosa. Seguro que desearía poder usar GCC 2.3, que estaba mucho menos orientado a los estándares que el moderno 4.2 + ... -

Menos orientado a los estándares y muchos peor codegen y una implementación de biblioteca estándar con errores, e inutilizable para la mayoría de las bibliotecas de C ++ de terceros (por ejemplo, Boost), etc. Suena como un mal deseo; -] -

2 Respuestas

Debe especializarse completamente en todo, así:

namespace __test {

template <int A, int B, typename C>
class Test
{
    template <int V> void check(C & a) { }
};

template <>
template <>
void Test<1, 2, int>::check<0> (int &)
{
}

}

O use una estructura auxiliar para evitar intentar especializar parcialmente el método de plantilla de una clase de plantilla (que GCC y muchos otros no entenderán):

namespace __test {

template <typename C, int V>
struct TestHelper
{
    static void check (C & a)
    {
    }
};

template <typename C>
struct TestHelper<C, 0>
{
    static void check (C & a)
    {
    }
};

template <int A, int B, typename C>
class Test
{
    template <int V> void check(C & a)
    {
        TestHelper<C, V>::check (a);
    }
};

}

contestado el 10 de mayo de 11 a las 17:05

Según mi lectura de la norma, lo que quiere hacer parece ser legal. Citando §14.7.3 / 18:

En una declaración de especialización explícita para un miembro de una plantilla de clase o una plantilla de miembro que aparece en el ámbito del espacio de nombres, la plantilla de miembro y algunas de sus plantillas de clase adjuntas pueden permanecer sin especialización, excepto que la declaración no debe especializar explícitamente una plantilla de miembro de clase si sus plantillas de clase adjuntas no están explícitamente especializadas también. En tal declaración de especialización explícita, la palabra clave template seguido por un plantilla-lista-de-parámetros se proporcionará en lugar de la template<> que precede a la declaración de especialización explícita del miembro. Los tipos de parámetros de plantilla en el objeto plantilla-lista-de-parámetros serán los mismos que los especificados en la definición de la plantilla principal.

Como estás especializando explícitamente un plantilla de función miembro preferible a plantilla de miembro de clase, debería estar bien; sin embargo, ni Comeau, GCC ni VC ++ permiten lo siguiente, que debemos tener la sintaxis correcta:

namespace test
{
    template<int A, int B, typename C>
    class Test
    {
        template<int V>
        void check(C& a) { }
    };

    template<int A, int B, typename C>
    template<>
    void Test<A, B, C>::check<0>(C& a) { }
}
  • Comeau dice error: a template declaration containing a template parameter list may not be followed by an explicit specialization declaration, lo cual tiene sentido si aplicamos la regla en §14.7.3 / 18 a las plantillas de funciones miembro también
  • GCC dice invalid explicit specialization before '>' token; enclosing class templates are not explicitly specialized, lo que nuevamente tiene sentido si aplicamos la regla en §14.7.3 / 18 a las plantillas de funciones miembro también
  • VC ++ dice error C2768: 'test::Test<A,B,C>::check' : illegal use of explicit template arguments, que no es un mensaje de error útil, pero generalmente coincide con los demás

My adivinar es que debe haber un informe de defectos archivado que tampoco permita especializaciones explícitas de plantillas de función miembro cuando las plantillas de clase adjuntas no están explícitamente especializadas también; sin embargo, no puedo decir esto definitivamente ya que la redacción de §14.7.3 / 18 no ha cambiado entre el estándar C ++ 03 y el C ++ 0x FDIS (lo que sucedería si se presentara un DR contra C ++ 03 y aceptado).

contestado el 13 de mayo de 11 a las 04:05

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.