Передавать указатели на функции-члены или не-члены в качестве параметров

У меня есть структура с именем Foo, которая содержит функцию, которая вызывает любой метод, который она передается и возвращает значение.

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

У меня есть метод с именем barFunc...

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

... которые можно передать в fooFunc

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

Но я также хочу, чтобы fooFunc принимала функции-члены, такие как bazFunc....

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

... чтобы называться так...

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

... но это не верно.

Все, что я нашел в отношении передачи функций-членов в качестве параметров, говорит о том, что нужно знать, из какого класса происходит объект, до того, как он будет вызван, а это значит, что мне придется создать 2 функции вместо одной.

Есть ли способ, который я еще не нашел, который потребовал бы только 1 метод fooFunc, но поддерживал бы функции, не являющиеся членами и членами?

3 ответа

Решение

Пост C++11, как и на другие ответы

до 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;
}

Принимать boost::function<signature> передать результат boost::bind()

bool free_func(std::string const& arg) { ... }

struct X {
    bool mem_func(std::string const& arg) { ... }
};

...
typedef boost::function<bool (std::string const& name)> func_t;

std::vector<func_t> funcs;
X x;

funcs.push_back(boost::bind(&X::mem_func, x, _1));
funcs.push_back(boost::bind(&free_func, _1));

С C++11 или boost ваша задача проста - но поскольку вы хотите иметь решение C++03, то, как предлагается в комментариях, используйте функцию-член шаблона:

struct Foo
{
    template <typename Function>
    unsigned char fooFunc(unsigned char param, Function getValueMethod)
    {
        return getValueMethod(param);
    }
};

Тогда с примером бесплатной функции вы не будете ничего менять:

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

С функцией-членом - просто используйте C++03 std::mem_fun/bind1st из C++03 <functional>:

#include <functional>
Foo foo2;
Baz baz;
foo2.fooFunc(10, std::bind1st(std::mem_fun(&Baz::bazFunc), &baz));
Другие вопросы по тегам