用标量乘以复数的valarray

时间:2016-09-15 16:55:03

标签: c++ c++11 stl complex-numbers valarray

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并找到了* overload定义:

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)

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

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起作用或者有些接近妥协呢?

2 个答案:

答案 0 :(得分:3)

  

有没有办法使它成为我的第一行代码v1 * 2.0工作或   一些密切的妥协?

是:将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是一个模板类,其operator*()(以及类似的运算符)仅在模板类型上定义。

因此,std::valarray<double>可以与double标量相乘,std::valarray<std::complex<double>>可以乘以std::complex<double>标量,但std::valarray<std::complex<double>>可以&#39}。 t乘以double标量。

答案 1 :(得分:3)

在这种情况下,专业化operator*是非法的,无法满足您的需求。

重载可能,但向namespace std添加重载是违法的。 (这可能会在

中发生变化

我们可以这样做:

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>