Reputation: 2077
For reasons unknown to me, my code stopped working today. For preimplemented functions I have a relay code like this
Math_Node& Function_Manager::relay_complex_to_std(Math_Node& arg, std::function<Complex(const Complex&)> f) const{
if( arg.children_.size() != 1 ){
throw std::runtime_error("Function expects exactly one argument.");
}
evaluate(*arg.children_[0]);
if( std::holds_alternative<Complex>(arg.children_[0]->data_) ){
arg.data_ = f(std::get<Complex>(arg.children_[0]->data_));
arg.children_.clear();
}
return arg;
}
with the types
using Decimal = double;
using Complex = std::complex<Decimal>;
This can be called by a different function like
Math_Node& Function_Manager::sqrt(Math_Node& arg) const{
//return relay_complex_to_std(arg, std::sqrt<Complex::value_type>);
return relay_complex_to_std(arg, [](Complex a){return std::sqrt(a);});
}
The commented line stopped working with the error message
In member function ‘Numeric_Calculator::Math_Node& Numeric_Calculator::Function_Manager::sqrt(Numeric_Calculator::Math_Node&) const’:
functionmanager.cpp:214:72: error:
no matching function for call to ‘Numeric_Calculator::Function_Manager::relay_complex_to_std(Numeric_Calculator::Math_Node&, unresolved overloaded function type>) const’
return relay_complex_to_std(arg, std::sqrt<Complex::value_type>);
Why is the function type not resolved? It works when I put it in a lambda.
Compiler:
g++-9 --version
g++-9 (Ubuntu 9.2.1-17ubuntu1~18.04.1) 9.2.1 20191102
edit:
Thanks to Jarod42 for pointing out the overload with valarray
. You can see for yourself that de-commenting the below line will result in the same error
#include <cmath>
#include <complex>
#include <functional>
#include <iostream>
//#include <valarray>
using Complex = std::complex<double>;
Complex relay(Complex arg, std::function<Complex(Complex)> f){
return f(arg);
}
int main(){
std::function<Complex(Complex)> f = std::sqrt<Complex::value_type>;
std::cout << std::sqrt(4.0) << "\n";
std::cout << relay(Complex(-2,0), std::sqrt<Complex::value_type>) << "\n";
return 0;
}
Upvotes: 0
Views: 87
Reputation: 217438
std::sqrt<double>
might be ambiguous, it might be
std::sqrt(std::complex<double>)
(not accepting std::sqrt(Integral)
double
)
And whereas std::complex
one might be converted to the expected std::function
, name resolution doesn't take that conversion into account.
See Address of an overloaded function for more details.
Upvotes: 1