我有以下定义
template <typename T1, typename T2> class ArithmeticType {
public:
T1 x1;
T2 x2;
typedef typeof(x1+x2) Type;
};
template <typename D1, typename D2> inline
std::complex<typename ArithmeticType<D1,D2>::Type>
operator+(const std::complex<D1>& x1, const std::complex<D2>& x2) {
D1 x1r = real(x1);
D1 x1i = imag(x1);
D2 x2r = real(x2);
D2 x2i = imag(x2);
return std::complex<typename ArithmeticType<D1,D2>::Type>(x1r+x2r, x1i+x2i);
}
Run Code Online (Sandbox Code Playgroud)
然后,我按如下方式使用此类
std::complex<double> x;
std::cout << typeid(x).name() << std::endl;
ArithmeticType<std::complex<double>,std::complex<float>>::Type y;
std::cout << typeid(y).name() << std::endl;
Run Code Online (Sandbox Code Playgroud)
产生输出
St7complexIdE
St7complexIdE
Run Code Online (Sandbox Code Playgroud)
这对我来说很有意义: y属于std::complex<double>
现在,随着添加复杂和浮动类型的缩进,我添加了operator+模板的特殊化,因此代码变为
template <typename T1, typename T2> class ArithmeticType {
public:
T1 x1;
T2 x2;
typedef typeof(x1+x2) Type;
};
template <typename D1, typename D2> inline
std::complex<typename ArithmeticType<D1,D2>::Type>
operator+(const std::complex<D1>& x1, const std::complex<D2>& x2) {
D1 x1r = real(x1);
D1 x1i = imag(x1);
D2 x2r = real(x2);
D2 x2i = imag(x2);
return std::complex<typename ArithmeticType<D1,D2>::Type>(x1r+x2r, x1i+x2i);
}
template <typename D1, typename D2> inline
std::complex<typename ArithmeticType<D1,D2>::Type>
operator+(const std::complex<D1>& x1, const D2 x2) {
D1 x1r = real(x1);
D1 x1i = imag(x1);
return std::complex<typename ArithmeticType<D1,D2>::Type>(x1r+x2, x1i+x2);
}
Run Code Online (Sandbox Code Playgroud)
我运行与以前相同的代码,但是现在出现编译错误,因为编译器尝试使用第二种特殊化方法而不是第一种特殊化方法。这对我来说没有意义。我认为(g ++)编译器仍会选择第一个专业化版本。
有人可以解释为什么会这样的规则吗?
第二个模板的问题是返回值的扣除:
template <typename D1, typename D2> inline
std::complex<typename ArithmeticType<D1,D2>::Type>
operator+(const std::complex<D1>& x1, const D2 x2)
Run Code Online (Sandbox Code Playgroud)
当你尝试实例化时ArithmeticType<std::complex<double>, std::complex<float> >
第二种operator+类型推导为:D1: double, D2: std::complex<float>。然后您尝试ArithmeticType使用D1=double,进行实例化D2=std::complex<float>。operator+这反过来又试图推断出adouble和的类型std::complex<float>。没有这个函数,编译失败。