将复数的 valarray 乘以标量

Multiplying a valarray of complex numbers by a scalar

valarray<double> 可以乘以一个标量。但是,当我想乘以 valarray<complex<double>> 的标量时出现错误。我想知道是否有办法以漂亮的方式做到这一点。这是问题的重现:

valarray<complex<double>> v1{ { complex<double>{1,0}, complex<double>{2,0}, complex<double>{3,0} } };
valarray<complex<double>> v2 = v1 * 2.0; // error

生成Error C2784: 'std::complex<_Other> std::operator *(const std::complex<_Other> &,const std::complex<_Other> &)': could not deduce template argument for 'const std::complex<_Other> &' from 'std::vector<std::complex<double>,std::allocator<_Ty>>'

所以我尝试构建自己的函数以查看是否可以完成以及以下工作:

valarray<complex<double>> VAMult(const valarray<complex<double>> &v, double scalar)
{
    valarray<complex<double>> out(v.size());
    for (size_t i = 0; i < v.size(); i++)
    {
        out[i] = v[i] * scalar;
    }
    return out;
}

// makes the following code work:
valarray<complex<double>> v2 = VAMult(v1, 2.0);

但是这个实现会产生非常难看的代码,所以我研究了 valarray.h 并找到了 * 重载定义:

operator*(const _Ty& _Left,
        const valarray<_Ty>& _Right)
{   // return scalar * valarray
    _VALOP(_Ty, _Right.size(), _Left * _Right[_Idx]);
}

#define _VALOP(TYPE, LENGTH, RHS)   /* assign RHS(_Idx) to new valarray */ \
valarray<TYPE> _Ans(LENGTH); \
for (size_t _Idx = 0; _Idx < _Ans.size(); ++_Idx) \
    _Ans[_Idx] = RHS; \
return (_Ans)

我对模板的了解非常有限,但是可以扩展这个 class 吗?这是我的尝试:

valarray<complex<double>> valarray<complex<double>>::operator*(const double &scalar)
{
    return valarray<complex<double>>{};
}

导致 Error C2039 '*': is not a member of 'std::valarray<std::complex<double>>'

有没有办法让我的第一行代码 v1 * 2.0 工作或一些妥协?

Is there a way to make it so my first line of code v1 * 2.0 works or some close compromise?

是:将 v1 乘以一个复标量。

以下代码编译

#include <complex>
#include <valarray>

int main()
 {
   std::valarray<std::complex<double>> v1{ { {1,0}, {2,0}, {3,0} } };
   std::valarray<std::complex<double>> v2 = v1 * std::complex<double>{2.0};
 }

问题是 valarray 是一个模板 class,带有 operator*()(和类似的运算符),仅在模板类型上定义。

所以 std::valarray<double> 可以乘以 double 标量,std::valarray<std::complex<double>> 可以乘以 std::complex<double> 标量,但 std::valarray<std::complex<double>> 不能' t 乘以 double 标量。

在这种情况下专攻 operator* 既是非法的,也不会得到你想要的。

可以重载,但向 namespace std 添加重载是非法的。 (这可能会在 or 中改变)

我们可以做到:

valarray<complex<double>> v1{ { complex<double>{1,0}, complex<double>{2,0}, complex<double>{3,0} } };
valarray<complex<double>> v2 = v1 * complex<double>{2.0};

但我想你知道。

您可以使用 named operators 并得到:

valarray<complex<double>> v2 = v1 *times* 2.0;

合法工作。

您也可以编写自己的文字到复数转换器:

std::complex<double> operator"" _cplx( long double t ) {
  return {(double)std::move(t)};
}

Live example.

但实际上,转换为 complex<double>