If the function is not static
, you cannot pass it in input to a function that accepts a non-member function pointer.
Consider that a non-static
member function has an implicit pointer to ClassName
as its first parameter, which points to the object on which the member function is being invoked.
struct X
{
static void foo() { } // Does not have an implicit "this" pointer argument
void bar() { } // Has an implicit "this" pointer argument
};
int main()
{
void (*f)() = &X::foo; // OK: foo is static
void (*g)() = &X::bar; // ERROR! bar is non-static
}
Here, not even std::bind()
will work, because the result is not convertible to a function pointer. Lambdas are convertible to function pointers, but only if they are non-capturing (and a lambda here would need to capture the object to invoke the member function on).
Therefore, the only (ugly) workaround is to have a global adapter function which invokes the member function on an object which is available through a global pointer variable. The global pointer variable is set prior to calling the function:
struct X
{
void bar() { }
};
void function_taking_a_function_pointer(void (*f)())
{
// Do something...
f();
}
X* pX = nullptr;
void bar_adapter()
{
pX->bar();
}
int main()
{
X x; // Some object I want to invoke the member function bar() on...
pX = &x; // Set the global pointer and invoke the function...
function_taking_a_function_pointer(bar_adapter);
}
If you want, you can make this slightly more flexible by turning bar_adapter
into a function template, and passing the pointer-to-member-function as a template argument:
template<typename T, void (T::*mf)()>
void adapter()
{
(pX->*mf)();
}
Here is how you would use it:
#include <iostream>
struct X
{
void foo() { std::cout << "X::foo()" << std::endl; }
void bar() { std::cout << "X::bar()" << std::endl; }
};
void function_taking_a_function_pointer(void (*f)())
{
// Do something...
f();
}
X* pX = nullptr;
template<typename T, void (T::*mf)()>
void adapter()
{
(pX->*mf)();
}
int main()
{
X x; // Some object I want to invoke the member function bar() on...
pX = &x; // Set the global pointer and invoke the function(s)...
function_taking_a_function_pointer(adapter<X, &X::foo>);
function_taking_a_function_pointer(adapter<X, &X::bar>);
}
Finally, here is a live example.