Consider three ways to implement a routine in c++: through functors, member functions, and non-member functions. For example,
#include <iostream>
#include <string>
using std::cout;
using std::endl;
using std::string;
class FOO
{
public:
void operator() (string word) // first: functor
{
cout << word << endl;
}
void m_function(string word) // second: member-function
{
cout << word << endl;
}
} FUNCTOR;
void function(string word) // third: non-member function
{
cout << word << endl;
}
Now consider a template-function to call the three functions above:
template<class T>
void eval(T fun)
{
fun("Using an external function");
}
What is the proper way to call FOO::m_function through eval?
I tried:
FUNCTOR("Normal call"); // OK: call to ‘void FOO::operator()(string)‘
eval(FUNCTOR); // OK: instantiation of ‘void eval(T) [with T = FOO]’
function("Normal call"); // OK: call to ‘void function(string)’
eval(function); // OK: instantiation of ‘void eval(T) [with T = void (*)(string)]’
FUNCTOR.m_function("Normal call"); // OK: call to member-function ‘FOO::m_function(string)’
eval(FUNCTOR.m_function); // ERROR: cannot convert ‘FOO::m_function’ from type
// ‘void (FOO::)(std::string) {aka void (FOO::)(string)}’
// to type ‘void (FOO::*)(std::basic_string<char>)’
// In instantiation of ‘void eval(T) [with T = void (FOO::*)(string)]’:
// ERROR: must use ‘.*’ or ‘->*’ to call pointer-to-member function in ‘fun (...)’, e.g. ‘(... ->* fun) (...)’
A pointer to member function and a pointer to function are two different beasts. The former takes an implicit first argument, the
thispointer, or in other words, a pointer to the instance on which the member function is to be invoked on.Typically, in order to be able to pass the member function as a callable object, you
bindthe instance on which it is to be invoked on, and then useplaceholdersto indicate arguments that will be passed to the callable later. In your caseThe first argument to
bindabove is the pointer to member function that you want to invoke, and the second is a pointer to theFOOinstance on which you want to invokem_function. The last one is a placeholder that indicates the first argument passed to the callable created bybindshould be used when calling the member function.Another way to do this is to pass a lambda expression to
evalthat takes achar const *(orstd::string const&) argument and calls the member function.Live demo