std::function als Class Member?



  • Ich arbeite mich grade in C++ std::function ein um verschiedene Callbacks zu realisieren. Gibt es eine Möglichkeit diese als Member einer Klasse zu halten und dabei Templates zu verwenden? Möchte nicht für jede mögliche Art eine eigene Klasse schreiben. Dabei sollen diese Funktionen verschiedene Parameter berücksichtigen.



  • Ja, du kannst den selben Trick wie std::function verwenden - Type Erasure.
    Wenn du genauer sagst, was du mahcne willst, kann ich oder jemand anders dir ein Beispiel schreiben.



  • Ich hab noch nichts implementiert. Spiele grad mögliche Gedanken durch. Ich wollte einen Handler haben der die verschiedenen Callbacks verwaltet.

    Eine methode ermöglicht die Registrierung der callbacks template basiert. Z.b.

    template <class ReturnValue>
    void registerCallback(const std::string& id)
    (
      hier wird die std::function erzeugt und
      als member gehalten
    )
    

    Wobei ich halt auch Parameter berücksichtigen wollte. Hab da an Variadics gedacht. Der erste Fall ohne Parameter sollte gehen Hab gesehen das dies oft gemacht wird. Meist als void der später gecastet wird. Nur wie geht das mit Parameter?



  • So ich habe mir mal weiter Gedanken gemacht und ein wenig rumgespielt. Inzwischen habe ich folgende Implementation um um Funktionspointer mit Parametern als Klassenmember halten zu können, die ich in einem STL Container speichern kann:

    class Callback
    {
    protected:
        Callback(){}	
    
    public:	
    	virtual ~Callback(){}
    
        template <typename R, typename... Args>
        R* run(Args &&... args)
        {	
    		auto C = static_cast<GenericCallback<R, Args&&...> *>(this);
    	    if(C!=0){
    			std::cout << "Cast completed" << std::endl;
    			return (*C)(std::forward<Args>(args)...);
    		}
    		else{
    			throw std::exception("Cast failed");
    		}
    	}
    
    	template <typename R, typename... Args>
        static Callback* create(std::function<R* (Args&& ... args)> func){
    		return new GenerickCallback<R, Args...>(func);
        }
    };
    
    template <typename R, typename... Args>
    class GenericCallback : public Callback
    {
    public:
    	GenericCallback(std::function<R* (Args&& ... args)> func)
    	:m_functor(func){}
    	virtual ~GenericCallback(){}
    
    	R* operator() (Args&& ... args){
    		return m_functor(std::forward<Args>(args)...);
    	}
    
    private:
    	std::function<R* (Args&& ... args)> m_functor = nullptr;
    };
    
    // Zum Test führe ich ein Factory Delegate durch
    int main {
    	std::function<Test*(const std::string&)> delegate = [&](const std::string& text) -> Test * { return new Test(text);};
    	Callback* d = Callback::create(delegate); 
    	Test* t1 = d->run<Test, const std::string&>("hallo Du da!");
    	t1->saySomething();
    

    Allerdings schlägt mir hier grundsätzlich der dynamic_cast Fehl,
    mit einem static cast läuft es. Kann mir jemand sagen, was ich
    falsch mache?


  • Mod

    Rogo schrieb:

    Kann mir jemand sagen, was ich falsch mache?

    Zunächst mal die Tatsache, dass der gezeigte Code nicht der ist, mit dem du getestet hast. Nachdem ich 3 Minuten damit verbracht habe, die fehlenden Klammern bei int main zu identifizieren, habe ich keine Lust mehr, mich mit diesem Code weiter zu beschäftigen, um der eigentlichen Frage nachzugehen.



  • Das ist mein Code, allerdings aus mehreren Dateien zusammen kopiert und um Testcode und Kommentare reduziert. Sorry für mögliche Copy und Paste Fehler.

    Nettes Forum wenn man hier gleich blöd angeraunt wird...



  • Rogo schrieb:

    Sorry für mögliche Copy und Paste Fehler.

    Mhmm. Bin jetzt nicht so sicher, daß noch jemand die Sache anschaut. Sehe keine bereinigte Version.

    Rogo schrieb:

    Nettes Forum wenn man hier gleich blöd angeraunt wird...

    Mhmm.


Log in to reply