2009-07-18 6 views
0

D'abord un avertissement, je remplace un tas de code qui utilise boost :: function et boost :: bind. Cependant, je passe à une base de code qui ne permet pas de RTTI. Je voudrais continuer à utiliser boost mais je ne sais pas s'il y a un moyen de contourner cette restriction. Donc, j'essaie d'imiter certaines de ses fonctionnalités, mais beaucoup plus simplifié. J'ai une classe de rappel:Functors C++ et zéro

template <class Class, typename ReturnType = void> class Callback0 { 
    typedef ReturnType (Class::*Method)(); 

    public: 
     Callback0(Class* object, Method method) 
      : m_object(object) 
      , m_method(method) 
     { 
      ; 
     } 

     Callback0(const Callback0& callback) 
      : m_object(callback.m_object) 
      , m_method(callback.m_method) 
     { 
      ; 
     } 

     operator bool() { 
      return m_object != 0; 
     } 

     operator bool() const { 
      return m_object != 0; 
     } 

     ReturnType operator()() { 
      return (m_object->*m_method)(); 
     } 

     Callback0<Class, ReturnType>& operator=(const Callback0<Class, ReturnType>& callback) { 
      if(this != &callback) { 
       m_object = callback.m_object; 
       m_method = callback.m_method; 
      } 

      return *this; 
     } 

    private: 
     Class* m_object; 
     Method m_method; 
}; 

Cela me permet de faire des callbacks simples avec des paramètres zéro:

class Meh { 
    public: 
     Meh() {;} 
     ~Meh() {;} 

     void f0() { 
      footprint6v("%s\n", __FUNCTION__); 
     } 
}; 


static void meh() { 
    Meh* m = new Meh; 

    Callback0<Meh, void> c0(m, &Meh::f0); 

    c0(); 
} 

Je voudrais être en mesure d'attribuer mes objets de rappel à zéro en tant que paramètres par défaut comme ceci:

class Wtf { 
    public: 
     Wtf() : m_callback(0) {;} 
     ~Wtf() {;} 

     void doSomething(const Callback0<Wtf, void>& callback = 0) { 
      m_callback = callback; 
     } 

    private: 
     Callback0<Wtf, void> m_callback; 
}; 

Cela fonctionne lorsque vous utilisez la fonction boost :: que vous pouvez faire:

class Wtf { 
    public: 
     Wtf() : m_callback(0) {;} 
     ~Wtf() {;} 

     void doSomething(const boost::function<void()>& callback = 0) { 
      m_callback = callback; 
     } 

    private: 
     boost::function<void()> m_callback; 
}; 

J'imagine que boost fait de la magie ici. Je sais que je peux simplement changer le paramètre en pointeur plutôt qu'en référence, mais comme je l'ai dit, je remplace beaucoup de code et je voudrais minimiser l'impact du changement de boost.

+0

"... ne permet pas RTTI." semble plutôt draconien et arbitraire. Pouvez-vous clarifier la raison derrière cette restriction? Si c'est une question de style, alors je ne suis pas sûr qu'une partie d'une dépendance étrangère puisse correspondre à la ligne directrice de style interne, mais ce n'est pas une raison pour interdire la dépendance externe, tant que vous l'utilisez des lignes directrices. Si le compilateur que vous ciblez ne supporte tout simplement pas cette partie de C++, eh bien, c'est une autre affaire. – SingleNegationElimination

+0

Merci pour le commentaire. Ce que je veux dire, c'est que le projet est compilé avec le drapeau -fno-rtti. Ainsi, pas de RTTI. – ohnnyj

Répondre

5

Boost ne fait rien de magique. 0 est juste un pointeur de fonction NULL pour le constructeur de pointeur de fonction.

Je suggère dans votre cas, vous fournissez simplement un constructeur par défaut

Callback0() : m_object(NULL), m_method(NULL) {} 

Et faire doSomething ressembler à

void doSomething(const Callback0<Wtf, void>& callback = Callback0<Wtf, void>()) { 
+0

Merci Logan. Au moment où j'ai reçu votre réponse, j'ai compris que c'était une question plutôt stupide avec une réponse simple. J'ai fini par créer un constructeur qui prend un paramètre entier pour contourner le fait d'appeler explicitement le constructeur par défaut dans la fonction prototype. – ohnnyj

+2

Si vous pensez que sa réponse est correcte, vous devez la marquer correctement, afin qu'il puisse obtenir le représentant pour cela. –