2017-10-28 61 views
9

我目前正在與模板掙扎:我有一個模板類A,執行基本的數學(爲花車,雙打,複數),看起來像這樣刪除多餘的模板類型

template <typename T> 
class A 
{ 
public: 
    void foo(std::vector<std::complex<T>>& result); 
}; 

現在我可以使用類似A<double>, A<float>,但我也想使用它,如A<std::complex<float>>A<std::complex<double>>。使用後者時,我想的foo定義看起來像

void foo(std::vector<std::complex<float>>& result); 

,而不是像

void foo(std::vector<std::complex<std::complex<float>>>& result); 

有沒有辦法來爲std::complex<T>案件一個特定的模板,我在其中能訪問「內部」類型?或者這是不可能的/不好的做法? 解決這個問題最優雅的方法是什麼?

回答

5

的另一種方式可以通過創建一種類型的性狀來檢測(提取物,當需要時)的浮子式

template <typename T> 
struct getFloatType 
{ using type = T; }; 

template <typename T> 
struct getFloatType<std::complex<T>> 
{ using type = T; }; 

A使用它(見fT

template <typename T> 
class A 
{ 
    public: 
     using fT = typename getFloatType<T>::type; 

     void foo(std::vector<std::complex<fT>>& result) 
     { } 
}; 
+0

這兩種方式是相同的,還是其中一種方式是這樣做的首選方式? – FlashTek

+0

@FlashTek - 他們真的不同;通過這種方式,您可以避免創建可以成爲優勢的專業化;但由於其他原因可能需要專業化;在這個玩具的例子中,我認爲這是首選的特質方式;但對於你的真實(我認爲更復雜)的必要性,專業化的方式可能更可取。只有你可以回答你的問題。 – max66

+0

@FlashTek如果你只是想改變'foo'的簽名,那麼這個更簡單。通過部分專業化,您可以自定義更多的內容,但是如您所問,您必須處理主要模板和部分專業化之間的重複代碼。 – songyuanyao

2

對於std::complex的任何實例,您可以製作partial specialization,例如,

template <typename T> 
class A<std::complex<T>> 
{ 
public: 
    void foo(std::vector<std::complex<T>>& result); 
}; 

那麼對於A<std::complex<double>>foo簽名會void foo(std::vector<std::complex<double>>& result);

要處理這些重複的代碼,您可以創建一個基類並將常用成員移入其中,並使主模板和部分特化都從其派生。例如

class Base { 
public: 
    void bar(...); 
}; 

然後

template <typename T> 
class A : public Base { 
    ... 
}; 

template <typename T> 
class A<std::complex<T>> : public Base { 
    ... 
}; 
+0

假設我在'A'類中有其他函數,是否還需要在部分規範中添加這些函數的定義? – FlashTek

+0

@FlashTek是的。您可以創建一個基類,並將普通成員移入其中,並使主模板和部分特化都從其派生。 – songyuanyao

+0

當我在頭文件中聲明函數並在body/cpp中定義函數時,是否可以重用代碼,還是需要在cpp中添加兩次定義? – FlashTek