如何解决是否可以从std :: bind对象访问参数?
请考虑以下情况。
一个假想弹出菜单类显示器的一些动作,并且当选择它们中的一个,它会调用在这在表单动作传递的std::function
:
PopupMenu::PopupMenu(std::function<void(RowItem*)> editRowFunction,RowItem *item)
: _editRowFunction(editRowFunction),_item(item) {
}
然后在某些时候它可能会调用execute:
PopupMenu::execute(} {
_editRowFunction(_item);
}
class EditorWidget {
void editRow(RowItem *row) {
//edit the row
}
}
这是我使用它们的全部方式:
int main() {
auto item = new RowItem();
auto editorWidget = new EditorWidget();
PopupMenu menu(std::bind(&EditorWidget::editRow,editorWidget,item),item);
menu.execute();
return 0;
}
一切正常。我的问题如下:
如果我已经在item
中传递了参数std::bind
,为什么必须再次将其作为第二个参数传递,以便能够使用该参数调用绑定函数?如果没有,尝试从PopupMenu::execute()
本身单独调用该函数,则会出现编译器错误。
PopupMenu::PopupMenu(std::function<void()> editRowFunction)
: _editRowFunction(editRowFunction) {}
如果我这样做,那么我会这样称呼:
PopupMenu::execute() {
_editRowFunction();
}
我对该方法不满意的是,我几乎可以在PopupMenu
构造函数中传递任何绑定函数,它将被调用。但这不是我想要的,我只想强制执行具有特定签名的功能。
我也可以通过lambda,是的。但是,让我们尝试不使用lambda来解决它。 预先感谢大家的帮助。
解决方法
std::bind(&EditorWidget::editRow,editorWidget,item)
std::bind
在这里创建一个函数对象,该函数对象使用参数EditorWidget::editRow
指向成员函数editorWidget
的指针,该指针绑定到对象item
。您所做的实际上是使用参数EditorWidget::editRow
将参数固定到函数item
。因此,有效地创建了一个不带参数的函数对象(因为已将其固定),并返回void
。
实际上PopupMenu
的构造函数不需要具有类型RowItem*
的第二个参数。您可以这样更改构造函数:
PopupMenu::PopupMenu(std::function<void()> editRowFunction)
: _editRowFunction(editRowFunction)
{
}
然后像这样调用函数对象:
PopupMenu::execute(} {
_editRowFunction();
}
在当前代码中,传递给构造函数_item
的函数对象未使用参数PopupMenu
。由于_editRowFunction
的类型为std::function<void(RowItem*)>
,因此可以满足编译器的要求。
下面是一个简单的例子来说明:
#include <iostream>
#include <functional>
struct callable
{
callable(std::function<void(std::string)> fn) : mFn(fn)
{}
std::function<void(std::string)> mFn;
void Run() { mFn("world"); }
};
struct Foo {
void print(std::string msg)
{
std::cout << msg << '\n';
}
};
int main()
{
Foo f;
auto fn = std::bind(&Foo::print,&f,"hello");
fn();
callable c(fn);
c.Run(); //expecting "world" to be printed
}
您可能期望输出为:
hello
world
但实际上是:
hello
hello
实时demo。
我能做的就是像这样更改功能对象的定义:
auto fn = std::bind(&Foo::print,std::placeholders::_1); //uses a placeholder
,我得到了预期的输出。您可以执行类似的操作,而不必对当前的实现进行很多更改。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。