Allow 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 was the compiler unable to resolve the address from the overloaded function real<float> ?

What overloaded functions does the compiler mean?

+7
source share
2 answers

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

Why overload?

26.4.9 Additional Overloads [cmplx.over]

  • 1 The following function templates must have additional overloads:

     arg norm conj proj imag real 
  • 2 Additional overloads should be sufficient to ensure:
    • If the argument is of type long double , then it is effectively mapped to complex<long double> .
    • Otherwise, if the argument is of type double or an integer type, then it is effectively added to complex<double> .
    • Otherwise, if the argument is of type float , then it effectively displays complex<float> .

[...]

The solution of the problem:

You can simply use a range based on ...

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

... or pack a call to real in a functor or other function ...

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

... or use a member function ...

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

IMPORTANT:

Note that when using transform : you should have enough space in the object:

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

or use the insertion device back:

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

Otherwise, you repeat undefined memory, causing undefined behavior.

+5
source

ยง26.4.9 indicates that (in particular) real should have additional overloads for arguments of type float, double and long double. It seems your libra implementation made a template for these overloads, perhaps like

 template <typename T> T real(T const& t) { return std::real(std::complex<T>{t}); } 

In addition to phresnel solutions, you can explicitly tell the compiler what kind of function pointer you have in mind:

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

Then the compiler searches for std::real , which can be converted to a function pointer of a given type and find the correct one.

I am telling you this for completeness only - I believe this explicit casting is ugly, and would prefer the range to be based or transformed using lambda.

+4
source

All Articles