C ++ for_each调用回调函数的向量并向每个函数传递一个参数

时间:2010-07-15 16:49:39

标签: c++ lambda callback foreach

当涉及到c ++ 0x,lambda等时,我是相当绿色的,所以我希望你们可以帮我解决这个小问题。

我想在向量中存储一堆回调,然后在时机成熟时使用for_each来调用它们。我希望回调函数能够接受参数。这是我现在的代码。问题在于void B :: do_another_callbacks(std :: string&)

#include <boost/bind.hpp>
#include <boost/function.hpp>
#include <vector>
#include <iostream>
#include <algorithm>



class A {
public:
    void print(std::string &s) {
        std::cout << s.c_str() << std::endl;
    }
};

typedef boost::function<void(std::string&)> another_callback;
typedef boost::function<void()> callback;

typedef std::vector<callback> callback_vector;
typedef std::vector<another_callback> another_callback_vector;

class B {
public:
    void add_callback(callback cb) {
        m_cb.push_back(cb);
    }

    void add_another_callback(another_callback acb) {
        m_acb.push_back(acb);
    }

    void do_callbacks() {
        for_each(m_cb.begin(), m_cb.end(), this);
    }

    void do_another_callbacks(std::string &s) {
        std::tr1::function<void(another_callback , std::string &)> my_func = [] (another_callback acb, std::string &s) { acb(s); }
        for_each(m_acb.begin(), m_acb.end(), my_func(_1, s));
    }

    void operator() (callback cb) { cb(); }

private:
    callback_vector m_cb;
    another_callback_vector m_acb;
};

void main() {
    A a;
    B b;
    std::string s("message");
    std::string q("question");
    b.add_callback(boost::bind(&A::print, &a, s));
    b.add_callback(boost::bind(&A::print, &a, q));
    b.add_another_callback(boost::bind(&A::print, &a, _1));
    b.do_callbacks();
    b.do_another_callbacks(s);
    b.do_another_callbacks(q);
}

我以为我可能会做这样的事情......

void do_another_callbacks(std::string &s) {

    for_each(m_acb.begin(), m_acb.end(), [&s](another_callback acb) {
        acb(s);
    });
}

但是这不能在MSVC2010中编译

1 个答案:

答案 0 :(得分:5)

长例子的问题是my_func(_1,s)就在那里被评估。您需要使用std::bind(或boost::bind)来调用范围中每个元素的函数。

您发布的替代代码确实有效,但由于do_callbacks中的代码,整个示例无法编译:

void do_callbacks() {
    for_each(m_cb.begin(), m_cb.end(), this);
}

this的类型为B*,不可调用。如果您定义result_type typedef以匹配operator()的返回类型,则可以使用std::ref(*this)。以下代码在MSVC10下编译并运行:

#include <functional>
#include <vector>
#include <iostream>
#include <algorithm>



class A {
public:
    void print(std::string &s) {
        std::cout << s.c_str() << std::endl;
    }
};

typedef std::function<void(std::string&)> another_callback;
typedef std::function<void()> callback;

typedef std::vector<callback> callback_vector;
typedef std::vector<another_callback> another_callback_vector;

class B {
public:
    void add_callback(callback cb) {
        m_cb.push_back(cb);
    }

    void add_another_callback(another_callback acb) {
        m_acb.push_back(acb);
    }

    void do_callbacks() {
        std::for_each(m_cb.begin(), m_cb.end(), std::ref(*this));
    }

    void do_another_callbacks(std::string &s) {

        std::for_each(m_acb.begin(), m_acb.end(), [&s](another_callback acb) {
                acb(s);
            });
    }

    typedef void result_type;
    void operator() (callback cb) { cb(); }

private:
    callback_vector m_cb;
    another_callback_vector m_acb;
};

int main() {
    A a;
    B b;
    std::string s("message");
    std::string q("question");
    b.add_callback(std::bind(&A::print, &a, s));
    b.add_callback(std::bind(&A::print, &a, q));
    b.add_another_callback(std::bind(&A::print, &a, std::placeholders::_1));
    b.do_callbacks();
    b.do_another_callbacks(s);
    b.do_another_callbacks(q);
}