I try to pass std::log as a functional argument, but it seems that there are overloaded implementations of std::log and the compiler failed to resolve it. Codes:
#include <cmath>
#include <iostream>
#include <vector>
#include <string>
#include <functional>
template <typename FOper>
double Eval(FOper fOper, double X)
{
return fOper(X);
}
int main(int argc, char* argv[])
{
std::function<double(double)> fPlus1 = std::bind(std::plus<double>(), 1.0, std::placeholders::_1);
std::cout<<Eval(fPlus1, 10.0)<<std::endl;
// how to write this fLog ?
//std::function<double(double)> fLog = std::log;
//std::function<double(double)> fLog = std::log<double>;
std::cout<<Eval(fLog, 10.0)<<std::endl;
return 0;
}
The complier prompts an error message if I uncomment either line of the definition of fLog:
error: conversion from '<unresolved overloaded function type>' to non-scalar type 'std::function<double(doubl
e)>' requested
Like Xeo explained, it is possible to get it to work even when the function is overloaded using an explicit cast. However, since you’re using std::function already (which is a C++11 feature), you might as well just use a lambda expression as initializer:
This is preferable in C++11 because it avoids overloading issues. Also, it is more efficient than wrapping a function pointer because it saves one level of indirection and therefore allows the lambda’s body to be inlined into the internal wrapper object’s function call operator.
It should probably be stressed that the use of std::function in your example is unnecessary since Eval is already a function template and the type parameter FOper can exactly match the type of the function object without the need to wrap it inside std::function. So, if you don’t need the type erasure you get by using std::function, you could just as well write