Forward Deklaration von Parameter vom Typ boost::function<int ()>



  • hi

    Ich möchte in einer Headerfile die Abhängigkeit zu <boost/function.hpp> entfernen.
    Die Memberfunktion

    setCallBack(boost::function<int ()> aCallBack);
    

    nimmt eine boost::function entgegen und speichert die Funktionsreferenz in dem pimpl.

    Kann mir jemand einen Tip geben, wie ich den Parameter für diese Funktion vorwärts-deklariere?

    Ich hab es schon mit vielen verschiedenen typedefs versucht, aber es wollte einfach nicht klappen.

    Vielen Danke!

    ~Martin

    //-----------
    // MyClass.h
    //-----------

    #include <boost/function.hpp>   // I want to remove this dependency
    
    class MyClass
    {
    public:
    	void setCallBack(boost::function<int ()> aCallBack);
    private:
    	MyClassImpl *m_Impl;
    
    }
    

    //-----------
    // MyClass.cpp
    //-----------

    #include "MyClass.h"
    #include <boost/function.hpp>
    
    class MyClassImpl
    {
    public:
    	MyClassImpl()  {};
    	~MyClassImpl()  {};
    
    	boost::function<int ()> aCallBack;
    };
    
    MyClass::MyClass()
    {
    	m_Impl = new MyClassImpl();
    }
    
    MyClass::~MyClass()
    {
    	delete m_Impl;
    }
    
    void MyClass::setCallBack(boost::function<int ()> aCallBack)
    {
    	m_Impl->callBack = aCallBack;
    }
    

  • Mod

    Die obligatorische Gegenfrage: Warum?

    Und die Antwort auf deine Frage: Man kann da vielleicht was Monströses mit templates zusammenfrickeln um das zu erreichen, aber erstmal will ich wissen, warum man sich die zusätzliche Mühe machen sollte, um den vorhandenen Code zu verunstalten.



  • Den Grund kann ich mir schon denken. Er möchte die Header-Datei boost-frei bekommen, um sie evtl. für andere Projekte anzubieten, welche nicht auf boost-basieren sollen/können.

    Normalerweise kann man keine template-Klassen vorwärts-deklarieren (bzw. nur mit sehr großem Aufwand, s. z.B. <iosfwd>).

    Mir kommt dann nur die explizite Änderung der setCallback-Funktion in den Sinn, d.h.

    void setCallBack(int (*aCallBack)());
    

    Dann entfällt aber auch die Allgemeingültigkeit bzgl. boost-Function.



  • hi SeppJ

    Ich schreibe momentan eine Library. Die Methode "setCallBack(boost::function<int ()> aCallBack)" wird nur innerhalb der Lib benutzt, aber einige andere Funktionen der Klasse MyLib müssen nach außen exportiert werden.

    Deshalb komme ich nicht drum herum die "MyClass.h" mit zu liefern. Die Abhänigkeit darin zu boost stört dann sehr, weil dann ja der Benutzer der Lib boost ebenfalls im IncludePfad haben muss.

    Gruß

    Martin



  • Naja, man könnte theoretisch ja auch tr1::function benutzen, aber ich weiß nicht, wie viele Compiler das bereitstellen. Hundert-prozentig sicher ist das auch nicht.

    Wieso brauchst du gerade function ? Müssen die Rückgabewerte mit in andere konvertierbar sein? Denn sonst würde es ein roher Funktionszeiger schon tun.



  • butze_124 schrieb:

    Die Abhänigkeit darin zu boost stört dann sehr, weil dann ja der Benutzer der Lib boost ebenfalls im IncludePfad haben muss.

    Was nun wirklich kein Weltuntergang ist! Deine Lib muß der User schließlich auch in den Include Path mit eintragen, oder? Eben! Dann kann er auch gleich noch Boost mit eintragen.

    Notfalls kann man ja die nötigen Boost Libs auch selber mit ausliefern, so das der User nichts für Boost eintragen muß. Das Boost-Tool bcp.exe[1] hilft da ein wenig.

    [1] http://www.boost.org/doc/libs/1_40_0/tools/bcp/bcp.html



  • hi,

    die Boost-Includes sollen nicht mitgeliefert werden. Ist auch nur nervig, wenn man sich als Anwender auch noch um solche Include kümmern muss. Da ich bislang alle anderen Abhängigkeiten aus meinem Programm entfernt habe, will ich es jetzt auch zuende bringen 🙂

    Naja, man könnte theoretisch ja auch tr1::function benutzen, aber ich weiß nicht, wie viele Compiler das bereitstellen. Hundert-prozentig sicher ist das auch nicht.

    Dann müsste der Anwender wieder sicherstellen, dass er tr1-Libraries bei sich installiert hat.

    Mir kommt dann nur die explizite Änderung der setCallback-Funktion in den Sinn, d.h.

    C/C++ Code:
    void setCallBack(int (*aCallBack)());
    

    Dann entfällt aber auch die Allgemeingültigkeit bzgl. boost-Function.

    Seit heute Morgen versuche ich jetzt schon boost::function durch "einfache" c++ FunctionPointer zu ersetzen. Aber so richtig bekomme ich das nicht hin 😞
    Nach vielen Syntaxfehlern und googlen bin ich auf die Seite

    http://www.codeproject.com/KB/cpp/FastDelegate.aspx

    gestoßen, die sich etwas mit meinen Problemen befasst.

    Beim Threaderstellen habe ich auch einige Details weggelassen. Mein Problem ist leider etwas komplexer, da mit Vererbung gearbeitet wird und eine Aggregationsklasse entsprechende Memberfunktionen aufrufen soll.

    aktuelle (funktionierende) Architektur mit boost::function (CallBack jetzt ohne parameter)

    class BaseClass
    {
    public:
    	virtual void interruptHandler() = 0;		//abstrakte Funktionsdeklaration
    	InterfaceClass *m_pIntf;	// Aggregation zur Interfaceklasse
    }
    
    classA1 : Base
    {
    public:
    	classA1() {m_pIntf->setInterruptHandler(boost::bind(&classA1::interruptHandler, this))};  //Konstruktor setzt den Callback
    	virtual void interruptHandler() { //do something };
    }
    
    classA2 : Base
    {
    public:
    	classA2() {m_pIntf->setInterruptHandler(boost::bind(&classA2::interruptHandler, this))};  //Konstruktor setzt den Callback
    	virtual void interruptHandler() { //do something };
    }
    
    class InterfaceClass
    {
    public:
    	void setCallBack(boost::function<void ()> callBack) {interruptHandler = callBack};  // speichert den callBack lokal ab in der Variablen interruptHandler
    
    private:
    	foo() {interruptHandler()};			//foo() soll entsprechende interruptHandler aus ClassA1 oder ClassA2 aufrufen
    	boost::function<void ()> interruptHandler;		//Member speichert Callback
    }
    
    main()
    {
    	classA1 a1;
    	// ein Interrupt kommt
    	// die Funktion foo() wird in der InterfaceClass (a1::m_pIntf::InterfaceClass) aufgerufen
    	// classA1::interruptHandler() wird ausgeführt.
    }
    

    Wenn ich das jetzt richtig verstanden habe lassen sich normale Memberfunktionszeiger nicht mehr mit der Vererbung vereinbaren.

    Kennt jemand evtl. ein Beispiel, wie ich das Problem lösen kann?

    Solange schaue ich mir noch <iosfwd>)an

    Gruß

    Martin



  • Ein anderer Tipp für dich:

    Mußt du denn unbedingt die setCallback-Methode in die öffentliche Schnittstelle packen? Du sagst ja selber, daß du es nur intern benötigst.

    Dann reich doch einfach eine Schnittstellenklasse nach außen und intern verwendest du eine davon abgeleitete Klasse, welche dann die setCallback-Methode anbietet.



  • Kann mir jemand einen Tip geben, wie ich den Parameter für diese Funktion vorwärts-deklariere?

    Wenns ein "function_fwd.hpp" File o.ä. gibt, dann include eben das, statt dem "ganzen" File.

    Sonst würde ich das eher bleiben lassen.

    Wenn du unbedingt willst, kannst du natürlich probieren, ob es so geht:

    namespace boost
    {
    template <class T> class function;
    } // boost
    


  • Wenn du unbedingt willst, kannst du natürlich probieren, ob es so geht:

    C/C++ Code:
    namespace boost
    {
    template <class T> class function;
    } // boost
    

    } // boost

    das hat auf Anhieb geklappt!

    Vielen Vielen Dank euch allen - ihr habt mir viel Arbeit mit dem Rumfrickeln mit den Funktionspointern erspart!

    Gruß

    Martin


Anmelden zum Antworten