2010-05-12 16 views
5

Tengo una clase de plantilla Matrix. Quiero especializar una función para el tipo complejo, donde T puede ser cualquier cosa. He intentado esto:Especialización de un miembro de una clase de plantilla para un tipo de parámetro de clase de plantilla

6 template <typename T> 
    7 class Matrix { 
    8  public : 
    9    static void f(); 
10 };   
11 template<typename T> void Matrix<T>::f() { cout << "generic" << endl; } 
12 template<> void Matrix<double>::f() { cout << "double" << endl; } 
13 template<typename T> void Matrix<std::complex<T> >::f() { cout << "complex" << endl; } 

La línea 13 no se compila. Cómo puedo hacer eso ?

+1

posible duplicado de [Especializado en un constructor de plantilla de clase] (http://stackoverflow.com/questions/2672536/specializing-a-class-template-constructor) –

+0

No veo cómo es esto un dup .. –

+0

Está tratando de especializar la función de miembro no plantilla. Lo mismo en esa pregunta. –

Respuesta

1

De hecho, encontré una manera inteligente de hacerlo a través de Boost. Como yo no quiero que mi biblioteca a depender de Boost, aquí está el código:

template <class T, T val> struct integral_constant 
{ 
     typedef integral_constant<T, val> type; 
     typedef T value_type; 
     static const T value = val; 
};  
typedef integral_constant<bool, true> true_type; 
typedef integral_constant<bool, false> false_type; 
template <typename T> struct is_complex : false_type{}; 
template <typename T> struct is_complex<std::complex<T> > : true_type{}; 

template <typename T> 
class Matrix { 
     public : 
      static void f() { f_(typename is_complex<T>::type()); } 
     private : 
      static void f_(true_type) { cout << "generic complex" << endl; } 
      static void f_(false_type) { cout << "generic real" << endl; } 
};   
template<> void Matrix<double>::f() { cout << "double" << endl; } 

De esta manera, puedo usar la sobrecarga de funciones y la plantilla para lograr mi objetivo.

0

como se describe en la respuesta relacionado, lo que necesita hacer es especializan toda la clase, en lugar de la simple función:

#include <iostream> 
#include <complex> 
using namespace std; 

template <typename T> 
class Matrix { 
public : 
    static void f(); 
}; 

template<typename T> void Matrix<T>::f() { cout << "generic" << endl; } 
template<> void Matrix<double>::f() { cout << "double" << endl; } 

template <typename T> 
class Matrix<std::complex<T> > { 
public: 
    static void f() { cout << "complex" << endl; } 
}; 

int main(void) { 
    Matrix<complex<double> >::f(); 
    return 0; 
} 
+0

No entiendo. ¿Por qué puedo especializarlo fácilmente para el doble, pero no para el complejo ? Lo que quiero es exactamente evitar especializar toda la clase ya que eso significa que necesito duplicar el código que debe reutilizarse. – Maxime

+0

También puede extraer f en otra clase y especializar todo lo que desee: Matrix podría implementar 'f()' como 'SpecializedF :: f (...)' – UncleBens

3

En las líneas 11 y 12 tiene declaración de especialización explícita para una miembro de una plantilla de clase permitida por C++ Standard 14.7/3 (14.5.2/2 también contiene un buen ejemplo). En la línea 13 intentas especializar parcialmente una plantilla de clase y eso no está permitido en esta forma (esto es especialización parcial porque no conoces todo el tipo std::complex<T> porque todavía depende de T). Deberías especializar parcialmente a toda la clase.

+0

como sugirió Assaf Lavie, ¿no se puede hacer usando parámetros de plantilla de plantilla sin tener que especializar parcialmente a toda la clase? Un conjunto de funciones será el mismo ya sea doble o complejo o flotante. No quiero tener que duplicar todas estas funciones. – Maxime

+0

Probablemente una buena idea será mover todas las funciones genéricas a la clase base y parcialmente especializar solo la clase heredada. –

Cuestiones relacionadas