2017-10-28 59 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