2010-12-08 71 views
1

J'ai un problème avec l'utilisation de boost :: bind et boost :: function et en passant boost :: function comme rappel dans une autre classe.C++ boost :: bind et boost :: function, fonctions de rappel de classe membres et opérateur ==. Qu'est-ce que je fais mal?

Voici un exemple qui est la situation problématique:

typedef boost::function<void (bool)> callbackFunction; 

class HasCallback 
{ 
public: 
HasCallback() : value(0) 
{ 
} 

int value; 

void CallBackFunction(bool changed) 
{ 
    std::cout << "HasCallback class. CallBackFunction called. Parameter: " << value << std::endl; 
} 
}; 

class ReceivesCallback 
{ 

public: 
void AddCallback(callbackFunction newFunc) 
{ 
    callbacks.push_back(newFunc); 
} 

void execute(int &i) 
{ 
    for(std::vector<callbackFunction>::iterator it = callbacks.begin(); it != callbacks.end(); it++) 
    { 
    (*it)(i++); 
    } 
} 

void RemoveHandler(callbackFunction oldFunc) 
{ 
    for(std::vector<callbackFunction>::iterator it = callbacks.begin(); it != callbacks.end(); it++) 
    { 
    if((*it) == oldFunc) 
    { 
    callbacks.erase(it); 
    break; 
    } 
    } 

} 

private: 
std::vector<callbackFunction> callbacks; 
}; 


int main() 
{ 
HasCallback hc; 
ReceivesCallback rc; 
rc.AddCallback(boost::bind(&HasCallback::CallBackFunction, &hc, _1)); 
hc.value = 123; 



HasCallback hc2; 
rc.AddCallback(boost::bind(&HasCallback::CallBackFunction, &hc2, _1)); 
hc2.value = 321; 

int a = 0; 

rc.RemoveHandler(boost::bind(&HasCallback::CallBackFunction, &hc2, _1)); 
rc.execute(a); 
} 

Le problème que je vais avoir est que cela ne même pas compiler. Il échoue dans ReceivesCallback :: RemoveHandler dans la ligne if ((* it) = oldFunc) avec l'erreur indiquant qu'il y a plus d'une surcharge de l'opérateur == pour la chose que j'essaie de faire. Je continue à chercher ceci et ne peux pas trouver ce que je fais mal. Aussi, je continue à trouver des informations contradictoires, l'une disant qu'il est possible de comparer boost :: function-s et un autre disant que ce n'est pas le cas. Je peux voir les fonctions opérateur == dans boost/function_base.hpp et je crois que cela est supposé fonctionner, je n'arrive pas à comprendre comment. Quelqu'un peut-il m'aider ici? Mon soupçon est qu'il échoue parce que les paramètres de boost :: bind doivent être spécifiés complètement (être des valeurs concrètes) mais c'est quelque chose que je ne peux pas obtenir dans le code que je développe, j'ai juste besoin de savoir si le gestionnaire passé est enregistré ou non, puisque je lie à un objet il doit avoir toutes les informations nécessaires pour faire la distinction.

Répondre

1

Voir la FAQ Boost.Function pour une explication: Why can't I compare boost::function objects with operator== or operator!= ?. Boost.Functions fournit uniquement la comparaison d'un boost::function avec un objet de fonction arbitraire

Je crois que rendre votre modèle de fonction membre RemoveHandler pourrait résoudre le problème:

template<class Functor> 
void RemoveHandler(const Functor &oldFunc) 
{ 
    for(std::vector<callbackFunction>::iterator it = callbacks.begin(); it != callbacks.end(); it++) 
    { 
     if((*it) == oldFunc) 
     { 
      callbacks.erase(it); 
      break; 
     } 
    } 
} 

Ici, oldFunc arrive à garder son type réel sans être « enveloppé » dans un boost::function.

+0

Merci, cela résout le problème et je comprends comment cela fonctionne. Je n'y aurais jamais pensé moi-même. Je suppose que j'ai encore beaucoup à apprendre en C++. – Max021