Wpmf-conversions warning



  • Hallo,
    ich bekomme bei einem Projekt von mir beim compilen eine warning, und zwar diese:

    warning: converting from 'void (Outside::Game::Object::*)()' to 'void*' [-Wpmf-conversions]
    

    In diesem Projekt habe ich eine Klasse für Callbacks, die ich über Function pointer identifiziere und aufrufe.
    Die funktion zum aufrufen ist die hier:

    template <class C, typename... P> void callEvent(void (C::*func)(P...), P... params)
    {
    	(*static_cast<Functor<P...>* >(m_functors[(void*) func]))(params...);
    }
    

    Die wird so aufgerufen:

    void Object::moved()
    {
    	callEvent(&Object::moved);
    }
    

    Prinzipiell funktioniert das so, dass ich den funktion pointer von der methode, die ein bestimmtes Event darstellt der key in einem Hash von Funktoren ist. Den pointer lege ich als void pointer ab.
    Jetzt ist die Frage ob ich dabei was falsch mache, es vielleicht sogar eleganter lösen kann oder was das Problem ist. Ich habe bisher nichts gefunden was mir irgendwie weiterhelfen würde.

    Wenn ihr den kompletten code sehen wollt kann ich den auch nochmal hier rein posten.

    Grüße



  • Nun, du konvertierst hier einen Funktionspointer in einen Objektpointer, das ist erstmal UB. Du könntest in void () () konvertieren, aber man fragt sich warum du nicht gleich std::function benutzt.
    Edit: Okay, weil du verschiedene Funktionstypen speicherst. Halte ich für keine so tolle Idee, die Warnung bekommst du mit void (
    ) () vielleicht weg, aber generell ist das natürlich niemals Typsicher hinzukriegen. Falls irgendwann mal jemand nicht die richtigen Argumente übergibt, stürzt das einfach hoffnungslos und ohne jeden Hinweis auf den Fehler ab. Sollte man vielleicht noch mal überdenken.



  • Die Warnung ist voellig berechtigt, in einer standardkonformen Implementierung (d.h. nicht MSVC) haben alle Memberfunktionszeiger die selbe Groesse, und die ist ueblicherweise 2 * sizeof(void*). Der Code ergibt auch keinen Sinn.



  • @cooky451
    Hm, das mit den falschen Parametern, die aufrufende Funktion hat doch die selben Parameter wie das Callback, also sollte es doch garnicht erst compilieren wenn man die falschen übergibt. Außer du meinst, dass genau das nicht gegeben ist, also die aufrufende Funktion andere Parameter hat als das Callback (z.B. einen Parameter mehr oder sowas in der Art).

    @Kellerautomat
    Inwiefern macht der Code keinen Sinn?



  • mupilz: Du speicherst nach void* gecastete Funktionszeiger in einer map, und castest sie hinterher wieder zurück in irgendetwas mit dem sie aufgerufen werden. An welcher Stelle soll der Compiler dich hier warnen oder sogar einen Fehler produzieren? Das schmiert einfach nur ab, sonst nichts. Und was Kellerautomat meint ist: Objectpointer != Functionpointer != Memberfunctionpointer



  • Ah, was ich meine ist, dass die aufrufende funktion ja die selben parameter hat wie das Callback, also z.B.

    class A : public Object
    {
    // ...
    	void someSender(int a, int b, int c)
    	{
    		callEvent(&A::someSender, a, b, c);
    	}
    // ...
    };
    
    class B
    {
    // ...
    	void someReceiver(int a, int b, int c)
    	{
    		// irgend ein code
    	}
    // ...
    };
    

    Dann wird das so aufgerufen:

    A sender;
    B* receiver = new B();
    sender.connect(&A::someSender, receiver, &B::someReceiver);
    // irgendwo anderst im code
    sender.someSender(5, 4, 3);
    

    Dann wird die methode someReceiver aufgerufen. Es wird also mit den Parametern von der someSender methode gecastet. Wenn man also die Zeile callEvent(&A::someSender, a, b, c); korrekt schreibt (was ich eigentlich vorraussetze) und beide methoden die gleichen Parameter haben (im prinzip auch total logisch das zu tun) sollte da nichts schief gehn.

    Und ich caste den Function pointer nur einmal, den brauch ich ja nur zur identifizierung, das andere ist ein Objekt(vielleicht kann man da ja sogar irgendwie überprüfen, ob es richtig gecastet wurde, zur Sicherheit).

    Das mit den Function/Object pointern ist jetzt klar.


Anmelden zum Antworten