-1

I have a vector of complex numbers and I need to sort them by their argument. Sadly, the numbers have type complex<int>, so function arg(c) returns an integer in range [-3,3] instead of a float and the numbers can't be sorted properly.

I've tried also

typedef complex<int> ci;
typedef complex<double> cd;

vector<ci> a;
sort(a.begin(), a.end(), [](ci v, ci u) { return arg(cd(v)) < arg(cd(u)); });

but it does not work either (compilation error: no matching function for call to ‘std::complex<double>::complex(ci&)). Can I sort these numbers without changing their type?

1 Answers1

3

You get the error because there is no converting constructor from std::complex<int> to std::complex<double> you have to construct the std::complex<double> by passing real and imaginary parts to the constructor:

#include <vector>
#include <complex>
#include <algorithm>

int main() {

    std::vector<std::complex<int>> a;
    std::sort(a.begin(), a.end(), [](const auto& v,const auto& u) {
        return std::arg(std::complex<double>(v.real(),v.imag())) < std::arg(std::complex<double>(u.real(),u.imag())); 
    });
}

Note that you can also use atan2 directly without constructing the std::complex<double> as mentioned by user17732522.

Last but not least, reconsider if you really need int with std::complex. From cppreference:

T - the type of the real and imaginary components. The behavior is unspecified (and may fail to compile) if T is not float, double, or long double and undefined if T is not NumericType.

Basically this means that you need to check the implementation you are using whether it supports std::complex<int> at all.

463035818_is_not_an_ai
  • 109,796
  • 11
  • 89
  • 185
  • 1
    You can also use `std::atan2` and skip the construction of `std::complex`. (Just be careful, the arguments are the other way around.) – user17732522 Mar 25 '22 at 22:37
  • That is funny, default implementation of template has such conversion constructor, but specialization for floating points do not have it (conversion is limited only between floating point types). So conversion from `std::complex` to `std::complex` works. IMO should work other way around. – Marek R Mar 25 '22 at 22:50
  • @MarekR As the answer now mentions, instantiating `std::complex` at all already has unspecified behavior. I am not sure why the definition of the primary template definition with e.g. this converting constructor was left in the standard. Maybe this was just meant to allow implementations room to define the behavior of `std::complex` and similar in whatever way they see fit? – user17732522 Mar 25 '22 at 23:12