Phlox Midas - 11 months ago 45

C++ Question

`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

generates

`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>>'`

So I tried to build my own function to see if it can be done and the following works:

`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);

But this implementation would make for really ugly code so I looked into valarray.h and found the * overload definition:

`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)

My knowledge of templating is very limited but is it possible to extend this class? Here's my attempt:

`valarray<complex<double>> valarray<complex<double>>::operator*(const double &scalar)`

{

return valarray<complex<double>>{};

}

resulting in

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

Is there a way to make it so my first line of code

`v1 * 2.0`

Answer Source

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

Yes: multiply `v1`

with a complex scalar.

The following code compile

```
#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};
}
```

The problem is that `valarray`

is a template class with an `operator*()`

(and similar operators) that is defined only over the template type.

So a `std::valarray<double>`

can be multiplied with a `double`

scalar, a `std::valarray<std::complex<double>>`

can be multiplied with a `std::complex<double>`

scalar but a `std::valarray<std::complex<double>>`

can't be multiplied with a `double`

scalar.