Std:: function с нестационарными функциями-членами
Я пытаюсь понять концепцию и ошибку. что с этим не так?
class A
{
public:
A()
{
std::function<void(int)> testFunc(&A::func);
}
private:
void func(int) {}
}
мой вопрос: возможно ли создать какой-либо объект, способный вызвать член определенного экземпляра, где std:: function действует как указатель на функцию-член, за исключением того, что не может быть использовано нечеткое определение типа, которое невозможно использовать как функциональные параметры в наследующих классах. например:
class A
{
public:
A()
{
index[WM_CREATE] = &A::close;
index[WM_DESTROY] = &A::destroy;
}
protected:
map<UINT msg, void (A::*)(HWND, UINT , WPARAM, LPARAM)> index;
void close(HWND,UINT, WPARAM, LPARAM);
void destroy(HWND, UINT, WPARAM, LPARAM);
};
class B : public A
{
public:
B()
{
index[WM_CREATE] = &B::create; // error because it not a pointer of type A::*
}
private:
void create(HWND, UINT, WPARAM, LPARAM);
};
Я думаю, что я нахожусь на правильном пути использования std:: functions следующим образом:
class A
{
public: // Gigantic stl error with these two
A() // |
{ // V
index[WM_CREATE] = std::function<void(HWND, UINT, WPARAM, LPARAM>(&A::close);
index[WM_DESTROY] = std::function<void(HWND, UINT, WPARAM, LPARAM>(&A::destroy);
}
protected:
map<UINT msg, std::function<void(HWND, UINT, WPARAM, LPARAM)> > index;
void close(HWND,UINT, WPARAM, LPARAM);
void destroy(HWND, UINT, WPARAM, LPARAM);
};
class B : public A
{
public: // and this one
B() // |
{ // V
index[WM_CREATE] = std::function<void(HWND, UINT, WPARAM, LPARAM)>(&B::create);
}
private:
void create(HWND, UINT, WPARAM, LPARAM);
};
если кто-то может объяснить, что означают эти гигантские критические ошибки и как их исправить, я бы очень признателен.
Ответы
Ответ 1
Я думаю, что проблема, с которой вы сталкиваетесь, заключается в том, что для функции-члена требуется не только указатель на функцию, но и указатель на вызывающий объект. Другими словами, функции-члены имеют дополнительный неявный аргумент, который является указателем на вызывающий объект.
Чтобы установить функцию-член в std:: функцию, вам нужно использовать std:: bind следующим образом:
std::function<void(int)> testFunc(std::bind(&A::func, this, _1));
Это связывает этот указатель текущего экземпляра с этой функцией, поэтому у него есть указатель на функцию и экземпляр объекта, для которого достаточно информации для правильного вызова функции. Аргумент _1 указывает, что первый явный аргумент будет предоставлен при вызове функции.
Ответ 2
мой вопрос: возможно ли создать какой-либо объект, способный вызвать член определенного экземпляра
В этом случае единственная потерянная информация - это то, какой конкретный экземпляр должен использовать объект std::function
: &A::func
не может использоваться сам по себе (например, (this->*&A::func)(0)
использует &A::func
с экземпляром *this
). Попробуйте:
std::function<void(int)> testFunc = std::bind(&A::func, this);
(Будьте осторожны, чтобы std::bind(&A::func, *this)
и std::bind(&A::func, this)
имели слегка отличную семантику.)
Ответ 3
С c ++ 11 вы также можете использовать лямбды, которые немного легче читать, чем std::bind
:
index[WM_CREATE] = [this](HWND h, UINT u, WPARAM w, LPARAM l)
{
create(h, u, w, l);
}