![](/img/trans.png)
[英]c++ template double std::complex<double> norm and product
[英]C++ templates - generalize scalar product for double and complex<double> vectors
我正在尝试使用模板重载*
运算符以计算vector<double>
和vector<complex<double>>
向量的标量积,并且在尝试了我所知道的一切之后我到达了这个:
#include <iostream>
#include <complex>
#include <vector>
using namespace std;
template<typename T> T operator* (const vector<T> &a, const vector<T> &b) {
T retvar; complex<double> c = 0;
for (int i = 0; i < b.size(); i++) c += conj(a[i])*b[i];
if (is_same<T, double>::value) retvar = c.real();
else retvar = c; // (*) the error is generated by this line
return retvar;
}
int main() {
vector<double> a, b;
a.push_back(5); b.push_back(3);
cout << a*b << endl;
return 0;
}
我想要做的是:我计算复数的标量积,然后我将它包含在模板给定的类型的变量中,以避免任何奇怪的转换。 但是,g++ 在第 (*) 行抛出以下错误:
error: assigning to 'double' from incompatible type 'complex<double>'
老实说,我的想法已经用完了,有什么好的方法可以在不使操作员过载两次的情况下摆脱这种情况?
不要重载您不拥有的类型的运算符。 相反,你可以写一个
template <typename T>
struct my_vect {
std::vector<T> data;
T operator* (const my_vect<T>& other);
};
接下来,无论参数的类型是什么, std::conj
返回一个复数。 在我看来,这是不幸的,因为在数学中,复向量和非复向量的标量积之间没有区别。 实数的共轭是实数。 要恢复那个不错的属性,可以使用my_conj
:
template <typename T> struct is_complex : std::false_type {};
template <typename T> struct is_complex<std::complex<T>> :std::true_type {};
template <typename T>
T my_conj(const T&t) {
if constexpr (is_complex<T>::value) return std::conj(t);
else return t;
}
现在,对于复数和非复数向量,标量积的定义可以相同。 完整示例:
#include <vector>
#include <complex>
#include <iostream>
#include <type_traits>
template <typename T> struct is_complex : std::false_type {};
template <typename T> struct is_complex<std::complex<T>> :std::true_type {};
template <typename T>
T my_conj(const T&t) {
if constexpr (is_complex<T>::value) return std::conj(t);
else return t;
}
template <typename T>
struct my_vect {
std::vector<T> data;
T operator* (const my_vect<T>& other) {
T result;
for (size_t i = 0; i < data.size(); i++) result += my_conj(data[i])*other.data[i];
return result;
}
};
int main() {
my_vect<double> x{{1,2,3}};
std::cout << x*x << '\n';
my_vect<std::complex<double>> y{{ {1,2} }};
std::cout << y*y;
}
PS:您应该检查两个向量的大小是否相同。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.