c++ - Especialización parcial de plantilla con error de argumento de plantilla múltiple
templates compiler-errors (2)
Cuando uso la especialización parcial de plantilla en una clase con un argumento de plantilla, puedo especializar un método como este:
#include <cstdlib>
template< std::size_t Dim >
class Test
{
public:
int foo();
};
template< std::size_t Dim >
inline int Test< Dim >::foo()
{
return 0;
}
template<>
inline int Test< 1 >::foo()
{
return 1;
}
int main()
{
Test< 2 > wTest2;
Test< 1 > wTest1;
wTest2.foo();
wTest1.foo();
return 0;
}
El método Foo está especializado para Dim = 1. Pero tan pronto como agregue un argumento de plantilla a mi clase, así:
#include <cstdlib>
template< typename T, std::size_t Dim >
class Test
{
public:
int foo();
};
template< typename T, std::size_t Dim >
inline int Test< T, Dim >::foo()
{
return 0;
}
template< typename T >
inline int Test< T, 1 >::foo()
{
return 1;
}
int main()
{
Test< double, 2 > wTest2;
Test< double, 1 > wTest1;
wTest2.foo();
wTest1.foo();
return 0;
}
El compilador (de VS2010) se queja de estos errores:
1>c:/documents and settings/cayouette/my documents/codelocal/testtemplatespecialization/main.cpp(20): error C3860: template argument list following class template name must list parameters in the order used in template parameter list
1>c:/documents and settings/cayouette/my documents/codelocal/testtemplatespecialization/main.cpp(20): error C2995: ''int Test<T,Dim>::foo(void)'' : function template has already been defined
1> c:/documents and settings/cayouette/my documents/codelocal/testtemplatespecialization/main.cpp(7) : see declaration of ''Test<T,Dim>::foo''
1>c:/documents and settings/cayouette/my documents/codelocal/testtemplatespecialization/main.cpp(20): error C2976: ''Test<T,Dim>'' : too few template arguments
1>c:/documents and settings/cayouette/my documents/codelocal/testtemplatespecialization/main.cpp(26): error C2264: ''Test<T,Dim>::foo'' : error in function definition or declaration; function not called
1> with
1> [
1> T=double,
1> Dim=2
1> ]
1>c:/documents and settings/cayouette/my documents/codelocal/testtemplatespecialization/main.cpp(27): error C2264: ''Test<T,Dim>::foo'' : error in function definition or declaration; function not called
1> with
1> [
1> T=double,
1> Dim=1
1> ]
1>
1>Build FAILED.
De la forma en que veo esto, no hay ambigüedad y el compilador debería poder resolver todo y funcionar como el caso de un solo argumento.
Si esto no es compatible con C ++, explique por qué.
No puede especializar parcialmente las funciones , esto incluye funciones de miembros. Solo puedes especializar parcialmente a toda la clase :
template< typename T, std::size_t Dim >
class Test
{
public:
int foo()
{
return 0;
}
};
template< typename T >
class test< T, 1 >
{
public:
int foo()
{
return 1;
}
};
(He definido las funciones en línea aquí, eso por supuesto no es necesario).
Editando porque todavía no puedo publicar comentarios (50 rep. Heh) ...
Philippe, en respuesta a tu comentario de esta mañana, según el estándar, no puedes especializar parcialmente a un miembro de una plantilla de clase, solo puedes especializarlo por completo (ya sea una plantilla de clase, una función, una plantilla de función, etc.) ) En su primer ejemplo, se está especializando completamente en la función miembro foo. En su segundo ejemplo, usted se está especializando parcialmente, por lo que no compilará. Usted puede especializarse completamente de esta manera:
template< >
inline int Test< int, 2 >::foo()
{...}
Aunque el snipet del código de Konrad es perfectamente legal, no estoy seguro de que el motivo proporcionado sobre por qué el código de Philippe no compila sea correcto. (Aunque, como mencionó Konrad, no se puede especializar parcialmente una plantilla de función).
El problema en cuestión, en el código de Philippe, es que estamos declarando una plantilla de clase y no una plantilla de función. Por lo tanto, se necesita una declaración de especialización de plantilla de clase parcial para que la definición de especialización parcial sea legal.
#include <cstdlib>
template< typename T, std::size_t Dim >
class Test
{
public:
int foo();
};
template < typename T >
class Test < T, 1 >
{
public:
int foo();
};
template< typename T, std::size_t Dim >
inline int Test< T, Dim >::foo()
{
return 0;
}
template< typename T >
inline int Test< T, 1 >::foo()
{
return 1;
}
int main()
{
Test< double, 2 > wTest2;
Test< int, 1 > wTest1;
wTest2.foo();
wTest1.foo();
return 0;
}