Я могу легко связать функции-члены с std::function
оборачивая их лямбда-выражением с предложением захвата.
class Class
{
Class()
{
Register([=](int n){ Function(n); });
}
void Register(std::function<void(int)> Callback)
{
}
void Function(int Number)
{
}
};
Но я хочу связать их напрямую, что-то вроде следующего.
// ...
Register(&Class::Function);
// ...
Я думаю, что в соответствии со стандартом C ++ 11 это должно поддерживаться. Тем не менее, в Visual Studio 11 я получаю эти ошибки компилятора.
ошибка C2440: «новая строка»: невозможно преобразовать из «int» в «класс *»
ошибка C2647: «. *»: невозможно разыменовать «void (__thiscall Class :: *) (int)» на «int»
Я думаю, что в соответствии со стандартом C ++ 11 это должно поддерживаться
Не совсем, потому что нестатическая функция-член имеет неявный первый параметр типа (cv-qualified) YourType*
так что в этом случае это не совпадает void(int)
, Отсюда необходимость std::bind
:
Register(std::bind(&Class::Function, PointerToSomeInstanceOfClass, _1));
Например
Class c;
using namespace std::placeholders; // for _1, _2 etc.
c.Register(std::bind(&Class::Function, &c, _1));
редактировать Вы упоминаете, что это должно быть вызвано с тем же Class
пример. В этом случае вы можете использовать простую функцию, не являющуюся членом:
void (int n) foo
{
theClassInstance.Function(n);
}
затем
Class c;
c.Register(foo);
По словам Стефана Т. Лававея — «Избегайте использования bind (), …, используйте лямбды».
https://www.youtube.com/watch?v=zt7ThwVfap0&т = 32m20s
В этом случае:
Class()
{
Register([this](int n){ Function(n); });
}
Ты можешь использовать std::bind
:
using namespace std::placeholders; // For _1 in the bind call
// ...
Register(std::bind(&Class::Function, this, _1));
С std::function
а также std::bind
, вы можете относиться к различным функциям класса одинаково.
#include <iostream>
#include <functional>
#include <vector>
using namespace std;
using namespace std::placeholders;
class Foo
{
public:
void foo(const string &msg)
{
cout << msg << '\n';
}
};
class Bar
{
public:
void bar(const string &msg, const string &suffix)
{
cout << msg << suffix << '\n';
}
};
int main(int argc, char **argv)
{
Foo foo;
Bar bar;
vector<function<void (const string &msg)>> collection;
collection.push_back(bind(&Foo::foo, &foo, _1));
collection.push_back(bind(&Bar::bar, &bar, _1, "bar"));
for (auto f : collection) {
f("foo");
}
return 0;
}