2010-07-15 6 views
3

Je suis assez vert quand il s'agit de C++ 0x, lambda, et ainsi j'espère que vous pourrez m'aider avec ce petit problème.C++ for_each appelant un vecteur de fonctions de rappel et passant chacun un argument

Je souhaite stocker un certain nombre de rappels dans un vecteur, puis utiliser for_each pour les appeler lorsque le moment est venu. Je veux que les fonctions de rappel puissent accepter des arguments. Voici mon code en ce moment. Le problème est en B vide :: 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); 
} 

Je pensais que je pourrais être en mesure de faire quelque chose comme ça ...

void do_another_callbacks(std::string &s) { 

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

Mais cela ne compile pas dans MSVC2010

+0

Le code ci-dessous devrait fonctionner * en principe * - Quelle erreur obtenez-vous? – Dario

Répondre

5

Le problème avec le long exemple est que my_func(_1,s) est évalué juste là et alors. Vous devez utiliser std::bind (ou boost::bind) pour appeler la fonction sur chaque élément de la plage.

Le code alternatif que vous avez publié ne fonctionne en effet, mais l'ensemble de l'exemple ne parvient pas à compiler en raison du code dans do_callbacks:

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

this est de type B*, qui ne sont pas remboursables par anticipation. Si vous définissez un typedef result_type pour correspondre au type de retour de operator(), vous pouvez utiliser std::ref(*this) à la place. Le code suivant compile et s'exécute sous 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); 
} 
+0

Génial! Merci beaucoup pour votre aide Anthony. – shaz