在集合上调用成员方法

时间:2018-01-06 15:42:33

标签: c++ c++11

我想知道在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吗?

3 个答案:

答案 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);