Search code examples
c++pointer-to-membernon-member-functions

Pass member OR non-member function pointers as parameters


I have a struct called Foo which contains a function that calls whatever method it is passed and returns the value.

struct Foo
{
    unsigned char fooFunc(unsigned char param, unsigned char(getValueMethod)(const unsigned char))
    {
        return getValueMethod(param);
    }
};

I have a method called barFunc...

static unsigned char barFunc(const unsigned char paramA)
{
    return paramA * 2;
}

...which can be nicely passed to fooFunc

Foo foo1;
foo1.fooFunc(10, &barFunc);

But I also want fooFunc to accept member functions, like bazFunc....

struct Baz
{
    unsigned char bazFunc(const unsigned char paramB)
    {
        return paramB * 3;
    }
};

...to be called like this...

Foo foo2;
Baz baz;
foo2.fooFunc(10, ?????);

...but that isn't valid.

Everything I have found on the subject of passing member functions as parameters talks about knowing what class the object comes from before it is called, which means I would have to create 2 functions instead of one.

Is there a way I haven't found yet, which would require only 1 fooFunc method but would support non-member and member functions?


Solution

  • post c++11, as per other answers

    pre c++11:

    #include <iostream>
    #include <functional>
    
    
    using namespace std;
    
    struct foo_holder {
    
        template<class T>
        unsigned char foo(unsigned char v, T f) {
            return f(v);
        }
    
    };
    
    unsigned char bar(unsigned char param) {
        return param * 2;
    }
    
    struct baz {
        unsigned char bar(unsigned char param) {
            return param * 3;
        }
    };
    
    int main()
    {
       cout << "Hello World" << endl; 
    
       foo_holder f;
       baz b;
    
       cout << static_cast<int>(
        f.foo(6, bar)
        ) << endl;
    
       cout << static_cast<int>(
        f.foo(6, std::bind1st(std::mem_fun(&baz::bar), &b))
        ) << endl;
    
       return 0;
    }