2009-07-18 11 views
0

Zuerst ein Disclaimer, ich ersetze einen Haufen Code, der boost :: function und boost :: bind verwendet. Ich ziehe jedoch zu einer Codebasis um, die rtti nicht erlaubt. Ich möchte weiterhin Boost verwenden, weiß aber nicht, ob es eine Möglichkeit gibt, diese Einschränkung zu umgehen.C++ Funktoren und Null

Also versuche ich, einige seiner Funktionen nachzuahmen, aber viel mehr vereinfacht. Ich habe einen Rückruf Klasse:

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(); 
} 

Ich möchte in der Lage sein zu meinen Rückruf Objekte auf Null als Default-Parameter zuweisen wie folgt:

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; 
}; 

Das bin ich einfach Rückrufe mit Null-Parameter erlaubt, zu tun:

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; 
}; 

Dies funktioniert, wenn boost :: function wie Sie tun können:

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; 
}; 

Ich stelle mir vor, Boost macht hier etwas Magie. Ich weiß, dass ich den Parameter nur zu einem Zeiger anstatt zu einer Referenz ändern kann, aber wie gesagt, ich ersetze viel Code und möchte den Einfluss der Änderung von Boost minimieren.

+0

aussehen "... nicht rtti nicht zulassen." wirkt eher drakonisch und willkürlich. Können Sie den Grund für diese Einschränkung erklären? Wenn dies eine Frage der Stilrichtlinien ist, bin ich mir nicht sicher, ob irgendein Teil einer Fremdabhängigkeit jemals vollständig der internen Stilrichtlinie entsprechen kann, aber das ist kein Grund, die externe Abhängigkeit nicht zuzulassen, solange Sie sie innerhalb der Richtlinien. Wenn der Compiler, auf den Sie abzielen, diesen Teil von C++ jedoch nicht unterstützt, dann ist das eine andere Sache. – SingleNegationElimination

+0

Danke für den Kommentar. Was ich sagen will ist, dass das Projekt mit der -fno-rtti-Flagge kompiliert wird. Also, kein rtti. – ohnnyj

Antwort

5

Boost macht nichts Magisches. 0 ist nur ein NULL-Funktionszeiger für den Funktionszeigerkonstruktor.

Ich würde in Ihrem Fall vorschlagen, dass Sie bieten nur einen Standardkonstruktor

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

Und doSomething wie

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

Danke Logan. Gerade als ich deine Antwort erhielt, dämmerte es mir, dass es eine ziemlich dumme Frage mit einer einfachen Antwort war. Ich habe schließlich einen Konstruktor erstellt, der einen ganzzahligen Parameter verwendet, um herumzukommen und den Standardkonstruktor explizit im Funktionsprototyp aufrufen zu müssen. – ohnnyj

+2

Wenn du denkst, dass seine Antwort richtig ist, solltest du sie als richtig markieren, damit er den Ruf dafür bekommt. –