1
votes

I have the following function:

void PerformAction(void(*pf_action)());

and the following class:

class A
{
public:
    void DoSomething();
}

I want to be able to do this:

int main()
{
    A a;
    PerformAction(&(a.DoSomething);

    return 0;
}

I have seen many answers that say that the function signature should be:

void PerformAction(void(A::*)());

This is not what I want.

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++?

2
Why not use std::function<void ()> as the parameter type? - James Adkison
member methods are different from free functions because they take an implicit this pointer as parameter, thus also a free function pointer is different from a member function pointer - 463035818_is_not_a_number

2 Answers

2
votes

Plain function pointers and member function pointers are different things.

Member functions take a hidden this parameter, whereas plain functions do not. To call a member function through a pointer an object is required to initialize that this parameter.

Hence, you cannot convert a pointer to a non-static member function to a plain function pointer and call through it without passing in an object.

1
votes

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()