我想知道在C ++ 11中是否有可能。这里的想法是让一个类保持对集合的引用,并提供一个通用的方法来对它执行一些操作。使用以下代码,我有问题使用bind:
调用集合中每个项的类的方法#include <iostream>
#include <vector>
#include <functional>
#include <algorithm>
using namespace std;
class Foo {
public:
void print() {
cout << "hello" << endl;
}
};
class Helper {
private:
vector<Foo> v;
public:
Helper() :
v(5) {
}
void perform(std::function<void(Foo&)>&& f) {
for_each(v.begin(), v.end(), f);
}
};
int main() {
Helper r;
r.perform(bind(&Foo::print)); //it doesn't work
r.perform([](Foo& f) {f.print();}); //it works
}
我猜bind
想要一个真实的Foo实例。我想知道是否可以使用bind而不是lambda。我问的只是因为我想了解C ++ 11的工作原理。是bind
需要mem_fn
吗?
答案 0 :(得分:3)
不,在您的情况下无法使用std::bind
。就像你说的那样,std::bind
需要一个Foo
的实例。顾名思义,它用于绑定对象到不会改变的函数,因此您不必每次都传递该对象。
void foo(int, bool) {}
int A = 10;
foo(A, false);
foo(A, true);
// now instead, I can "bind" A to foo.
auto foo2 = std::bind(&foo, A, std::placeholders::_1);
foo2(false);
foo2(true);
但不要担心,您可以直接传递&Foo::print
。为什么?因为perform
使用第一个参数Foo&
的函数,这正是print
所采用的函数(它没有任何显式参数,但具有隐式Foo&
)。
r.perform(&Foo::print);
答案 1 :(得分:2)
有很多方法可以做到这一点。但首先,您需要了解您的问题所在:
void perform(std::function<void(Foo&)>&& f) {
该参数是一个可调用对象,它以Foo &
为参数,并返回void
。这是宣称的内容。
r.perform(bind(&Foo::print));
std::bind
的目的是包装一个可调用对象并为其中一些参数提供默认值,同时从调用上下文转发其余参数。
这里没有默认参数可以绑定到任何东西。在可调用对象的上下文中,类方法(如Foo::print
)将指向其对象的指针作为其第一个参数,在本例中为Foo *
,即要调用的实际对象,以及这里没有绑定到任何东西的默认对象。 std::bind
没有做到这一点。它不可能在这里服务于任何逻辑目的。
第二个问题是:
for_each(v.begin(), v.end(), f);
for_each
将 引用 传递给集合中的对象,并传递给为其第三个参数指定的可调用对象。在这里,不知何故,你想在这里得到一个类方法,但是类方法将 指针 带到对象。
撇开如何使所有事物融合在一起的问题,没有直接的方法来调和这两者。一件事&#34;想要一个指针,另一件事想要一个参考。你必须改变一些事情。
更改此for_each
非常简单:
void perform(const std::function<void(Foo *)> &f) {
for_each(v.begin(), v.end(), [&](auto &g){ f(&g); });
}
现在,perform
采用一个可调用对象,该对象将指针作为其第一个参数,并使用内部lambda进行必要的转换。
如何称呼这个?您不需要std::bind
:
r.perform(&Foo::print);
那就是它。 std::function
的构造函数将负责包装所有内容。
答案 2 :(得分:1)
另一种方法是接收指向Foo
方法的指针,并将其称为迭代Foo
向量中的v
元素。
我的意思是......像
void performMethod (void(Foo::*f)())
{
for ( auto & obj : v )
(obj.*f)();
}
可以称为
r.performMethod(&Foo::print);