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?
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 tocomplex<long double>.- Otherwise, if the argument is of type
doubleor an integer type, then it is effectively added tocomplex<double>.- Otherwise, if the argument is of type
float, then it effectively displayscomplex<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.
ยง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.