Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

resolve address from overloaded function std::real<float>

std::vector<std::complex<float> > c;
std::vector<float> d;
std::transform(c.begin(), c.end(), d.begin(), std::real<float>);

Why couldn't the compiler resolve the address from the overloaded function real<float>?

Which overloaded functions does the compiler mean?

like image 664
Vadim Yemets Avatar asked Apr 03 '13 06:04

Vadim Yemets


1 Answers

Your library implementation has provided additional overloads for std::real<float>.

Why the overloads?

26.4.9 Additional overloads [cmplx.over]

  • 1 The following function templates shall have additional overloads:

    arg norm
    conj proj
    imag real
    
  • 2 The additional overloads shall be sufficient to ensure:
    1. If the argument has type long double, then it is effectively cast to complex<long double>.
    2. Otherwise, if the argument has type double or an integer type, then it is effectively cast to complex<double>.
    3. Otherwise, if the argument has type float, then it is effectively cast to complex<float>.

[...]

Solutions to problem:

You could just use a range based for ...

for (auto v : c) d.push_back(real(v));

... or pack the call to real into a functor or another function ...

struct my_caller {
    template <typename T> T operator() (std::complex<T> const &c) {
        return real(c);
    }
};

... or use the member function ...

std::transform(c.begin(), c.end(), d.begin(), [](std::complex<T> const &c) { 
    return c.real();
});

IMPORTANT:

Note that you have to have enough space in the target when using transform:

std::vector<float> d (c.size());

or use a back inserter:

std::transform(c.begin(), c.end(), back_inserter(d), ...);

Otherwise you are iterating over undefined memory, yielding undefined behaviour.

like image 195
Sebastian Mach Avatar answered Sep 18 '22 10:09

Sebastian Mach