How to Pass a Member Function Pointer

How can I pass a member function where a free function is expected?

There isn't anything wrong with using function pointers. However, pointers to non-static member functions are not like normal function pointers: member functions need to be called on an object which is passed as an implicit argument to the function. The signature of your member function above is, thus

void (aClass::*)(int, int)

rather than the type you try to use

void (*)(int, int)

One approach could consist in making the member function static in which case it doesn't require any object to be called on and you can use it with the type void (*)(int, int).

If you need to access any non-static member of your class and you need to stick with function pointers, e.g., because the function is part of a C interface, your best option is to always pass a void* to your function taking function pointers and call your member through a forwarding function which obtains an object from the void* and then calls the member function.

In a proper C++ interface you might want to have a look at having your function take templated argument for function objects to use arbitrary class types. If using a templated interface is undesirable you should use something like std::function<void(int, int)>: you can create a suitably callable function object for these, e.g., using std::bind().

The type-safe approaches using a template argument for the class type or a suitable std::function<...> are preferable than using a void* interface as they remove the potential for errors due to a cast to the wrong type.

To clarify how to use a function pointer to call a member function, here is an example:

// the function using the function pointers:
void somefunction(void (*fptr)(void*, int, int), void* context) {
fptr(context, 17, 42);
}

void non_member(void*, int i0, int i1) {
std::cout << "I don't need any context! i0=" << i0 << " i1=" << i1 << "\n";
}

struct foo {
void member(int i0, int i1) {
std::cout << "member function: this=" << this << " i0=" << i0 << " i1=" << i1 << "\n";
}
};

void forwarder(void* context, int i0, int i1) {
static_cast<foo*>(context)->member(i0, i1);
}

int main() {
somefunction(&non_member, nullptr);
foo object;
somefunction(&forwarder, &object);
}

Passing a pointer to a member function as argument for a void* function

I want to able to pass it any function/method that receives no parameters and returns void. Not just member methods of A or just global functions.

Is this possible in C++?

Yes, it is possible, but you need to use a more flexible type. The way to achieve this is to specify the PerformAction function with a different type. You want to use a type that is callable with zero arguments and returns void, std::function<void ()>. For example change the PerformAction function to be: void PerformAction(std::function<void ()> fn);. This version will allow you to accept anything that's callable with zero arguments and returns void, see the following code for an example.

Example Code

#include <functional>
#include <iostream>

class Foo
{
public:
void bar() { std::cout << "Member function: Foo::bar()\n"; }
};

void bar()
{
std::cout << "Free function: bar()\n";
}

class Functor
{
public:
void operator()() { std::cout << "Functor object\n"; }
};

auto lambda = []() { std::cout << "Lambda expression\n"; };

void doSomething(std::function<void ()> fn)
{
fn();
}

int main()
{
doSomething(bar);
doSomething(Functor());
doSomething(lambda);

Foo foo;
doSomething(std::bind(&Foo::bar, &foo));

return 0;
}

Live Example

Example Output

Free function: bar()
Functor object
Lambda expression
Member function: Foo::bar()

How do I pass a member function to a function that expects a function pointer?

The problem here is that a member function expects a "hidden" first argument that is a this pointer. Loosely speaking, a member function

void Func(int a, double b);

is equivalent to a free function

void Func(MyClass* this, int a, double b);

There is no way to pass a this pointer via ClassicFuncPtr, and std::function tricks won't help you here. target() doesn't do any magic, it just returns a pointer to the stored function if types match, and in your code they don't, that's why you get a null pointer. std::bind returns a functional object (that stores this inside), but a functional object is quite distinct from a function pointer and can't be converted into one.

Given that you can't change the callback type, there is a pretty ugly and fragile work-around that uses a static variable to store the value of this pointer. It should give you the idea of how to make it work, at least in principle.

class MyClass {
public:
void Test() {
thisPtr = this;
CallMyFunc(MemberFuncInvoker);
}

private:
inline static MyClass* thisPtr;

static void MemberFuncInvoker(int a, double b) {
thisPtr->MemberFunc(a, b);
}

void MemberFunc(int a, double b) {
std::cout << "a = " << a << ", b = " << b << '\n';
}
};

Note that static member functions don't expect a hidden this argument and behave like free functions in this respect (due to the absence of this argument, you can't access non-static data members inside a static member function).

Demo


Typically, callbacks are accompanied with a void*-like parameter that can be used to pass a this pointer. For example, theEnumWindows function from WinAPI has the signature

BOOL EnumWindows(WNDENUMPROC lpEnumFunc, LPARAM lParam);

That lParam is passed to a callback

BOOL CALLBACK EnumWindowsProc(HWND hwnd, LPARAM lParam);

Then, inside a free (or static) callback function you could do:

reinterpret_cast<MyClass*>(lParam)->MyMemberFunction(hwnd);

Passing a function pointer to a member function in C++.Getting error

Let's deal with the two issues in the post.

  1. You are calling fun1 and fun2. Since their return type is void, you can't pass their result as something's value. In particular as the value of a function pointer. You also can't obtain their address by using the dot member access operator. Which brings us to the following.

  2. Member functions are not like regular functions. You cannot just take their address. Their treatment is special, because member functions can only be called on an object. So there's a special syntax for them, which involves the class they belong to.

Here's how you would do something like what you are after:

class student
{
public:
void fun1() { printf("Fun1\n"); }
void fun2() { printf("Fun2\n"); }

// A function that receives a member function
// as parameter and calls the function
void wrapper(void (student::*fun)())
{
(this->*fun)();
}
};

int main()
{ student s;

s.wrapper(&student::fun1);
s.wrapper(&student::fun2);
return 0;
}

Pass member function pointer to parent class yields compiler error

If I understand the goal (and believe me, that's a sketchy 'if'), you want to specify some member of some A derivation to invoke from some A member as a dispatched 'callback' mechanic. If that is the case, then to answer your question in comment, yes, a function and bind can do this. It can even be semi-protected with a little help from sfinae:

Example

#include <iostream>
#include <type_traits>
#include <functional>
#include <memory>

struct A
{
virtual ~A() = default;

std::function<void(int)> callback = [](int){};

template<class Derived>
std::enable_if_t<std::is_base_of<A, Derived>::value>
registerCallback(void (Derived::*pfn)(int))
{
using namespace std::placeholders;
callback = std::bind(pfn, dynamic_cast<Derived*>(this), _1);
}

void fire(int arg)
{
callback(arg);
}
};

struct B : public A
{
void memberfn(int arg)
{
std::cout << __PRETTY_FUNCTION__ << ':' << arg << '\n';
}
};

struct Foo
{
void memberfn(int arg)
{
std::cout << __PRETTY_FUNCTION__ << ':' << arg << '\n';
}
};

int main()
{
std::unique_ptr<A> ptr = std::make_unique<B>();
ptr->registerCallback(&B::memberfn);
// ptr->registerCallback(&Foo::memberfn); // WILL NOT WORK
ptr->fire(42);
}

Output

void B::memberfn(int):42

The Parts

The first part is straight forward. We declare a member variable callback to be a std::function<void(int)> instance. This is where we'll eventually bind our callable object point. The default value is a lambda that does nothing.


The second part is... a little more complicated:

template<class Derived>
std::enable_if_t<std::is_base_of<A, Derived>::value>
registerCallback(void (Derived::*pfn)(int))

This declares registerCallback as an available member function that accepts a non-static member function pointer taking one int as an argument, but only if the class hosting that member function, or a derivative therein, is a derivation of A (or A itself). Some non-A derivative Foo with a member void foo(int) will not compile.


Next, the setup to the callback itself.

using namespace std::placeholders;
callback = std::bind(pfn, dymamic_cast<Derived*>(this), _1);

This just binds the pointer-to-member to this dynamic-cast to the derivation type (which had better work or we're in trouble, see final warning at the end of this diatribe), and sets the call-time placeholder. The _1 you see comes from the std::placeholders namespace, and is used to delay providing an argument to the callback until such time as we actually invoke it (where it will be required,and you'll see that later). See std::placehholders for more information.


Finally, the fire member, which does this:

void fire(int arg)
{
callback(arg);
}

This invokes the registered function object with the provided argument. Both the member function and this are already wired into the object. The argument arg is used to fill in the placeholder we mentioned earlier.


The test driver for this is straightforward:

int main()
{
std::unique_ptr<A> ptr = std::make_unique<B>();
ptr->registerCallback(&B::memberfn);
// ptr->registerCallback(&Foo::memberfn); // WILL NOT WORK
ptr->fire(42);
}

This creates a new B, hosting it in a dynamic A pointer (so you know there is no funny business going on). Even with that, because B derived from A the registerCallback sfinae filtering passes inspection and the callback is registered successfully. We then invoke the fire method, passing our int argument 42, which will be sent to the callback, etc.


Warning: With great power comes great responsibility

Even those there is protection from passing non-A derived member functions, there is absolutely none from the casting itself. It would be trivial to craft a basic A, pass a B member (which will work since A is its base), but there is no B actually present.

You can catch this at runtime via that dynamic_cast, which we're currently not error checking. For example:

registerCallback(void (Derived::*pfn)(int))
{
using namespace std::placeholders;
Derived *p = dynamic_cast<Derived*>(this);
if (p)
callback = std::bind(pfn, p, _1);
}

You can choose the road more risky. Personally, i'd detect the null case and throw an exception just to be safe(er)

Pass Member Function as Parameter to other Member Function (C++ 11 <function>)

ClassName::add is a non-static member function, an instance of ClassName is needed for it to be called on; it can't be used as the argument for std::function<double (double,double)> directly.

You can use lambda and capture this (as @Igor Tandetnik commented):

return intermediate(a, b, [this](double x, double y) { return add(x, y); } );

or use std::bind and bind this pointer:

return intermediate(a, b, std::bind(&ClassName::add, this, _1, _2));

or make ClassName::add a static member function or a non-member function (it could be because it doesn't use any members of ClassName). e.g.

class ClassName
{
public:
static double add(double a, double b);
...
};


Related Topics



Leave a reply



Submit