繁体   English   中英

C++ 模板 - 为双倍和复数推广标量积<double>向量

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM