将复数的 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
添加重载是非法的。 (这可能会在 c++20 or c++23 中改变)
我们可以做到:
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)};
}
但实际上,转换为 complex<double>
。
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
添加重载是非法的。 (这可能会在 c++20 or c++23 中改变)
我们可以做到:
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)};
}
但实际上,转换为 complex<double>
。