Multiplying complex with constant in C++
Asked Answered
K

3

9

The following code fails to compile

#include <iostream>
#include <cmath>
#include <complex>

using namespace std;

int main(void)
{
    const double b=3;
    complex <double> i(0, 1), comp;

    comp = b*i;

    comp = 3*i;

    return 0;
}

with error: no match for ‘operator*’ in ‘3 * i’ What is wrong here, why cannot I multiply with immediate constants? b*i works.

Knead answered 15/4, 2010 at 18:11 Comment(0)
S
7

In the first line:

comp = b*i;

The compiler calls:

template<class T> complex<T> operator*(const T& val, const complex<T>& rhs);

Which is instanced as:

template<> complex<double> operator*(const double& val, const complex<double>& rhs);

In the second case, there is no appropriate template int, so the instancing fails:

comp = 3.0 * i; // no operator*(int, complex<double>)
Solenne answered 15/4, 2010 at 18:18 Comment(0)
J
7

the std::complex class is a little bit stupid... define these to allow automatic promotions:

// Trick to allow type promotion below
template <typename T>
struct identity_t { typedef T type; };

/// Make working with std::complex<> nubmers suck less... allow promotion.
#define COMPLEX_OPS(OP)                                                 \
  template <typename _Tp>                                               \
  std::complex<_Tp>                                                     \
  operator OP(std::complex<_Tp> lhs, const typename identity_t<_Tp>::type & rhs) \
  {                                                                     \
    return lhs OP rhs;                                                  \
  }                                                                     \
  template <typename _Tp>                                               \
  std::complex<_Tp>                                                     \
  operator OP(const typename identity_t<_Tp>::type & lhs, const std::complex<_Tp> & rhs) \
  {                                                                     \
    return lhs OP rhs;                                                  \
  }
COMPLEX_OPS(+)
COMPLEX_OPS(-)
COMPLEX_OPS(*)
COMPLEX_OPS(/)
#undef COMPLEX_OPS
Jemadar answered 27/7, 2018 at 9:42 Comment(4)
awesome, this is so much better than writing a ton of operatorsNarcoanalysis
Why is it not there by default in std ? Is it because it would be too complicated to generalize to using simultaneously some complex<float>, complex<int>, complex<double> and complex<long double> for instance? Or is there a trap even if you only use complex<double>?Barlow
not any more, the complex classes date way back to early c++, so probably whatever reasoning was used back then no longer really applies now, (you can probably find some original discussion if you're dead-set on knowing) but nevermind - no use wringing our hands, we're stuck with them as they are.Jemadar
this is incredibleTrinatte
L
4

See http://www.cplusplus.com/reference/std/complex/complex/operators/ for an overview of the complex operators.

You will notice that the operator* is a template and will use the template parameter of the complex class to generate that code. The number literal you use to invoke operator* is of type int. Use comp = 3. * i;

Lullaby answered 15/4, 2010 at 18:17 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.