2010-05-12 5 views
5

Mam szablon macierzy klasy szablonowej. Chcę specjalizować funkcję dla kompleksu typu, gdzie T może być cokolwiek. Próbowałem tego:Specjalizacja członka klasy szablonu dla typu szablonu klasy szablonu

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; } 

Linia 13 nie jest kompilowana. Jak mogę to zrobić ?

+1

możliwy duplikat [Specjalizujący się konstruktor szablonów klas] (http://stackoverflow.com/questions/2672536/specialising-a-class-template-constructor) –

+0

Nie widzę, jak to jest dup .. –

+0

Stara się specjalizować funkcję nie-szablonu. To samo w tym pytaniu. –

Odpowiedz

1

W rzeczywistości znalazłem sprytny sposób, aby to zrobić poprzez Boost. Ponieważ nie chcę, moja biblioteka będzie uzależniona od Boost oto kod:

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; } 

ten sposób można użyć funkcji przeciążanie i szablon do osiągnięcia mojego celu.

0

Jak opisać w połączonej odpowiedzi, co musisz zrobić, to Specjalizujemy całą klasę, zamiast prostego funkcję:

#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

Nie rozumiem. Dlaczego mogę z łatwością specjalizować go pod kątem podwójnego, ale nie skomplikowanego ? To, czego chcę, to unikanie specjalizacji całej klasy, ponieważ oznaczałoby to konieczność skopiowania kodu, który powinien zostać ponownie użyty. – Maxime

+0

Możesz także wyodrębnić f do innej klasy i wyspecjalizować to, co tylko chcesz: Matrix może zaimplementować 'f()' jako 'SpecializedF :: f (...)' – UncleBens

3

W liniach 11 i 12 trzeba deklarację wyraźnej specjalizacji dla członek szablonu klasy dozwolonego w C++ Standard 14.7/3 (14.5.2/2 zawiera również dobry przykład). W linii 13 próbujesz częściowo specjalizować szablon klasy, a to nie jest dozwolone w tej formie (jest to częściowa specjalizacja, ponieważ nie znasz całego typu std::complex<T>, ponieważ nadal zależy od T). Powinieneś częściowo specjalizować całą klasę.

+0

jak sugerował Assaf Lavie, nie można tego zrobić za pomocą parametry szablonu szablonu bez konieczności częściowej specjalizacji całej klasy? Kilka funkcji będzie takich samych, jak to jest podwójne lub złożone lub float. Nie chcę duplikować wszystkich tych funkcji. – Maxime

+0

Prawdopodobnie dobrym pomysłem będzie przeniesienie wszystkich ogólnych funkcji do klasy bazowej i częściowa specjalizacja tylko dziedziczonej klasy. –