Operator overloading error for complex data

I wrote this code

1
2
3
4
5
6
7
8
9
10
vector<complex<double>> y1,y2;
//some stuff
vector<complex<double>> W_N;
//some other stuff
vector<complex<double>> term1(N/2), term2(N/2); //N is size of W_N
for(size_t n = 0; n < N/2; n++)
{
    term1[n] = y1[n] + W_N[n] * y2[n];
    term2[n] = y1[n] + W_N[(N/2)+n] * y2[n];
}


And compiling this throws this error.

1
2
3
4
5
6
7
error: ambiguous overload for 'operator*' (operand types are '__gnu_cxx::__alloc_traits<std::allocator<std::complex<double> >, std::complex<double> >::value_type' {aka 'std::complex<double>'} and '__gnu_cxx::__alloc_traits<std::allocator<std::complex<double> >, std::complex<double> >::value_type' {aka 'std::complex<double>'})|

candidate: 'std::complex<_Tp> std::operator*(const std::complex<_Tp>&, const std::complex<_Tp>&) [with _Tp = double]'|

candidate: 'std::complex<_Tp> operator*(std::complex<_Tp>&, TT&) [with T = double; TT = std::complex<double>]'|

candidate: 'std::complex<_Tp> operator*(TT&, std::complex<_Tp>&) [with T = double; TT = std::complex<double>]'|


I don't get why the call is ambiguous. To note, this is part of my attempt to implement Cooley-Turkey FFT algorithm in C++.

Any help is appreciated. Thank you.
Interesting issue. From reading your error message it seems your compiler is not sure what version of the * operator to work with?
This is not throwing an error on g++, so I can't test it. From what I'm reading you need to give the compiler a little help to determine what to do.
I'm not sure if this would resolve it or not, but try wrapping the complex variables in parenthesis...
term1[n] = (y1[n]) + (W_N[n]) * (y2[n]);

Other way to solve it is to cast it...?
term1[n] = ((complex<double>) y1[n]) + ((complex<double>) W_N[n]) * ((complex <double>) y2[n]);

Sorry, I hope one of those helped. Anyone here using Visual Studios who might be able to help?
Last edited on
Sorry, for not mentioning. I'm using CodeBlocks IDE and gcc compiler. I'll try the parenthesis for now.
Type-casting solved the problem. But I'm still confused about how the compiler could get confused.
I don't completely understand it myself, but the operator is overloaded three different ways:
( https://www.cplusplus.com/reference/complex/complex/operators/ )
template<class T> complex<T> operator*(const complex<T>& lhs, const complex<T>& rhs);
template<class T> complex<T> operator*(const complex<T>& lhs, const T& val);
template<class T> complex<T> operator*(const T& val, const complex<T>& rhs);

The compiler was not sure which one should be given a stronger weight in this situation, so it stalled out rather than trying to guess. This is safe behavior in general since you wouldn't want it guessing wrong and resulting in undefined behavior in a finished software product.
@newbieg I understand that. I am confused since each vector element is explicitly a complex<double>, for both operand vectors. So, the first candidate should be picked. It should not be ambiguous- is what I think.
And you would think your problem would be more widespread on the internet since I'd assume a lot of people who work with complex would be using doubles and would use the * operator too, but I could not find any post with this specific issue.
Mind if I ask what version of G++ you're on? Mine is Ubuntu 10.3.0 I'm still trying to get mine to throw the same error and it's not causing one.
Last edited on
Here's a minimal example of the problem:

1
2
3
4
5
6
7
8
9
10
11
12
#include <cstdio>

void foo(int const&, int const&) { std::puts("a"); }
template <typename T> void foo(int&, T&) { std::puts("b"); }
template <typename T> void foo(T&, int&) { std::puts("c"); }

int main()
{
    int a;
    int b;
    foo(a, b);
}
@Rabik771, I can't reproduce your problem. What does this do with your compiler?
Are you sure that the error that you state is referring to the lines you have posted?

1
2
3
4
5
6
7
8
9
10
11
12
#include <iostream>
#include <vector>
#include <complex>
using namespace std;

int main()
{
   vector<complex<double>> W = { { 1.0, 2.0 }, { 3.0, 4.0 } };
   vector<complex<double>> Z = { { 5.0, 6.0 }, { 7.0, 8.0 } };

   for ( int i = 0; i < 2; i++ )  cout << W[i] * Z[i] << '\n';
}


(-7,16)
(-11,52)
Last edited on
@newbieg, I'm using CodeBlocks 20.03, compiler: gcc 5.1.0, standard: c++17

@lastchance, Your snippet doesn't throw any error. I tried a similar snippet before posting here. There wasn't any problem. The problem only pops out in a FFT function I wrote.

If you're curious, here's the entire function.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
#include <iostream>
#include <vector>
#include <complex>
#define _USE_MATH_DEFINES

using namespace std;

vector<complex<double>> FFT(const vector<complex<double>>& X)
{
    using namespace std::complex_literals;
    size_t N = X.size();

    if(N == 1){return X;}

    else
    {
        //if((N%2) != 0){return CZT(X);}
        //else
        {
            vector<complex<double>> y1, y2;
            for(size_t n = 0; n < N; n++)
            {
                if((n%2) == 0)
                {
                    y1.push_back(X[n]);
                }
                else
                {
                    y2.push_back(X[n]);
                }
            }
            y1 = FFT(y1);
            y2 = FFT(y2);

            vector<complex<double>> W_N(N);
            for(size_t n=0; n<N; n++){W_N[n] = double(n);}
            for(auto& n: W_N)
            {
                n = exp(-2.0i * M_PI * n / double(N));
            }

            vector<complex<double>> term1(N/2), term2(N/2);
            for(size_t n = 0; n < N/2; n++)
            {
                term1[n] = y1[n] + W_N[n] * y2[n];    //error here
                term2[n] = y1[n] + W_N[(N/2)+n] * y2[n];    //and here
            }
            term1.insert(term1.end(), term2.begin(), term2.end());
            return term1;
        }
    }
}

int main()
{
   vector<complex<double>> X = { { 1.0, 2.0 }, { 3.0, 4.0 } };
   FFT( X );
}
Last edited on
@mbozzi, your example makes sense and is similar but then there should be error in @lastchance's snippet too. However, that doesn't happen.
@Rabik771,
To make a complete compileable example (which you could easily have done) I put before your code:
1
2
3
4
#include <iostream>
#include <vector>
#include <complex>
using namespace std;


and after your code:
1
2
3
4
5
6
int main()
{
   vector<complex<double>> X = { { 1.0, 2.0 }, { 3.0, 4.0 }, { 5.0, 6.0 }, { 7.0, 8.0 } };
   vector<complex<double>> XTILDE = FFT( X );
   for ( auto e : XTILDE ) cout << e << '\n';
}

commented out the line with CZT in, and set my own value for PI.


It produced no compiler errors. I simply can't reproduce your result.


You will have to show your whole code. [EDIT: which you've now done.
Last edited on
@Rabik771
Your code (at the time that I'm writing this post) compiles fine in cpp.sh.

Are you sure that the errors are occurring in the code that you have posted and not some previous version?
Last edited on
@lastchance, I'm sorry for not adding the includes and main. Showing the whole code is difficult as its a fairly large DLL. The FFT function should be standalone. The error is from current version where I have yet to complete CZT function.

And weirdly, after writing two more lines for CZT function (same file) the error is just gone. Now it compiles properly.
Note: I have added two more process lines for CZT function but no return statement.
Rakib771 wrote:
And weirdly, after writing two more lines for CZT function (same file) the error is just gone. Now it compiles properly.


Well, try reverting the CZT function and see if your problem reappears. Sometimes compilers obscure where the problem actually lies.

There was nothing wrong with the original complex multiplies.
@lastchance, could be. I'll try that later.

Thank you everyone for your kind assistance.
Topic archived. No new replies allowed.