2010-09-14 24 views
1

J'ai une liste de Thing et un Controller que je veux notify() avec chacune des choses. Le code ci-dessous fonctionne:Appelez la fonction membre C++ avec chaque élément d'une liste?

#include <algorithm> 
#include <iostream> 
#include <tr1/functional> 
#include <list> 
using namespace std; 

class Thing { public: int x; }; 

class Controller 
{ 
public: 
    void notify(Thing& t) { cerr << t.x << endl; } 
}; 

class Notifier 
{ 
public: 
    Notifier(Controller* c) { _c = c; } 
    void operator()(Thing& t) { _c->notify(t); } 
private: 
    Controller* _c; 
}; 

int main() 
{ 
    list<Thing> things; 
    Controller c; 

    // ... add some things ... 
    Thing t; 
    t.x = 1; things.push_back(t); 
    t.x = 2; things.push_back(t); 
    t.x = 3; things.push_back(t); 

    // This doesn't work: 
    //for_each(things.begin(), things.end(), 
    //   tr1::mem_fn(&Controller::notify)); 

    for_each(things.begin(), things.end(), Notifier(&c)); 
    return 0; 
} 

Ma question est: puis-je me débarrasser de la classe Notifier en utilisant une version de la ligne « Cela ne fonctionne pas »? On dirait que je devrais être capable de faire fonctionner quelque chose, mais je n'arrive pas à obtenir la bonne combinaison. (J'ai tâtonné avec un certain nombre de combinaisons différentes.)

Sans utiliser boost? (Je le ferais si je le pouvais.) J'utilise g ++ 4.1.2, oui je sais que c'est vieux ...

Répondre

4

Vous pouvez accomplir ceci en utilisant bind, qui est originaire de Boost mais est inclus dans TR1 et C + + 0x:

using std::tr1::placeholders::_1; 
std::for_each(things.begin(), things.end(), 
       std::tr1::bind(&Controller::notify, c, _1)); 
+0

Merci James, c'est exactement ce que je cherchais. – bstpierre

3

Qu'en est-old-school aller:

for(list<Thing>::iterator i = things.begin(); i != things.end(); i++) 
    c.notify(*i); 
+1

Parce que c'est trop évident? :) Honnêtement, c'est pour l'apprentissage, j'essaie de comprendre la nouvelle façon de le faire. – bstpierre