Necesito especializar la función de miembro de plantilla para algún tipo (digamos doble ). Funciona bien, mientras que la clase en Xsí no es una clase de plantilla, pero cuando la hago, la plantilla GCC comienza a dar errores en tiempo de compilación.
#include <iostream>
#include <cmath>
template <class C> class X
{
public:
   template <class T> void get_as();
};
template <class C>
void X<C>::get_as<double>()
{
}
int main()
{
   X<int> x;
   x.get_as();
}
Aquí está el mensaje de error
source.cpp:11:27: error: template-id
  'get_as<double>' in declaration of primary template
source.cpp:11:6: error: prototype for
  'void X<C>::get_as()' does not match any in class 'X<C>'
source.cpp:7:35: error: candidate is:
  template<class C> template<class T> void X::get_as()
¿Cómo puedo solucionarlo y cuál es el problema aquí?
Gracias por adelantado.
                    
                        c++
                                templates
                                gcc
                                specialization
                                
                    
                    
                        ledokol
fuente
                
                fuente

Respuestas:
No funciona de esa manera. Usted tendría que decir lo siguiente, pero es no correcta
template <class C> template<> void X<C>::get_as<double>() { }Los miembros explícitamente especializados necesitan que sus plantillas de clases circundantes también estén explícitamente especializadas. Por lo tanto, debe decir lo siguiente, que solo especializaría al miembro
X<int>.template <> template<> void X<int>::get_as<double>() { }Si desea mantener la plantilla circundante sin especializar, tiene varias opciones. Prefiero las sobrecargas
template <class C> class X { template<typename T> struct type { }; public: template <class T> void get_as() { get_as(type<T>()); } private: template<typename T> void get_as(type<T>) { } void get_as(type<double>) { } };fuente
type<>envoltura? ¿No podríaThacer el truco una conversión de un 0 a un puntero de tipo ? Supongo que no es tan elegante ...template<typename T> void get_as(T*); void get_as(double*);y pasar un(T*)0.Si uno puede usar
std::enable_if, podríamos confiar en SFINAE (la falla de sustitución no es un error)que funcionaría así (ver EN VIVO ):
#include <iostream> #include <type_traits> template <typename C> class X { public: template <typename T, std::enable_if_t<!std::is_same_v<double,T>, int> = 0> void get_as() { std::cout << "get as T" << std::endl; } template <typename T, std::enable_if_t<std::is_same_v<double,T>, int> = 0> void get_as() { std::cout << "get as double" << std::endl; } }; int main() { X<int> d; d.get_as<double>(); return 0; }Lo feo es que, con todos estos enable_if, solo una especialización necesita estar disponible para el compilador, de lo contrario surgirá un error de desambiguación. Es por eso que el comportamiento predeterminado "obtener como T" también necesita habilitar si.
fuente