deduced conflicting types for parameter bei function-pointer



  • Hallo,

    ich habe folgende Funktion f:

    #include <iostream>
    using namespace std;
    
    template<class T, class V, typename A1>
    void f(A1 a, T *target, void (V::*method)(A1))
    {
    }
    
    struct S
    {
    	void mf1(int)
    	{
    
    	}
    	void mf2(int&)
    	{
    
    	}
    };
    
    int main() {
    	S s;
    	f(1, &s, &S::mf1);
    	f(1, &s, &S::mf2);
    	return 0;
    }
    

    Und erhalte den Fehler:

    prog.cpp:24:18: error: no matching function for call to ‘f(int, S*, void (S::*)(int&))’
    f(1, &s, &S::mf2);

    Muss ich für f jetzt alle Kombinationen von by value/ref const oder nicht,... angeben oder kann man den oben genannten Fehler auch geschickt los werden?

    Jemand ne Idee?

    Gruß



  • Kommt das hier infrage?

    template<typename T0, typename OT,
             void (T::*MemFun)( T0 )>
    void f( T0 p0, OT& Obj )
    {
       (Obj.*MemFun)( p0 );
    }
    
    struct S1
    {
       void mf1( int )
       {
       }
    
       void mf2( int& )
       {
       }
    };
    
    int main()
    {
       S1 s;
       int i = 2;
       f<int ,S1,&S1::mf1>( 2, s );
       f<int&,S1,&S1::mf2>( 2, s );
    }
    

    Kann mir gut vorstellen, dass es mit C++11 schönere Lösungen gibt.



  • Denk doch mal nach.

    Dein Template-Parameter A1 kann doch entweder zu int&& oder zu int& deduziert werden und du mischst beides.

    Machs neu.



  • @DocShoe: Du hast 2 kleine Fehler bei dir drin (Z. 2 und 24):

    #include <iostream>
    #include <functional>
    using namespace std;
    
    template<typename T0, typename OT,
             void (OT::*MemFun)( T0 )> // OT statt T
    void f( T0 p0, OT& Obj )
    {
       (Obj.*MemFun)( p0 );
    }
    
    struct S1
    {
       void mf1( int )
       {
       }
    
       void mf2( int& )
       {
       }
    };
    
    int main()
    {
       S1 s;
       int i = 2;
       f<int ,S1,&S1::mf1>( 2, s );
       f<int&,S1,&S1::mf2>( i, s ); // i statt 2
    }
    


  • Das war nur ein Test um zu gucken, ob jemand aufpasst 😉



  • DocShoe schrieb:

    Kommt das hier infrage?

    Nee, nicht so wirklich.


  • Mod

    Jockelx schrieb:

    prog.cpp:24:18: error: no matching function for call to ‘f(int, S*, void (S::*)(int&))’
    f(1, &s, &S::mf2);

    Muss ich für f jetzt alle Kombinationen von by value/ref const oder nicht,... angeben oder kann man den oben genannten Fehler auch geschickt los werden?

    Warum bestehts du darauf, dass der Parametertyp deiner Funktion mit dem Parametertypen des übergebenen Zeigers auf Memberfunktion übereinstimmen muss?

    template<class T, class C, typename FA1, typename A1>
    void f(FA1&& a, T *target, void (C::*method)(A1));
    

    Eine andere Möglichkeit wäre, Typdeduktion für das erste Funktionsargument zu unterdrücken.

    template<class T, class C, typename A1>
    void f(std::remove_extent_t<A1> a, T *target, void (C::*method)(A1));
    


  • Hallo,

    camper schrieb:

    Warum bestehts du darauf, dass der Parametertyp deiner Funktion mit dem Parametertypen des übergebenen Zeigers auf Memberfunktion übereinstimmen muss?

    es geht um das Problem

    Kurz und knapp:

    onClick().connect(boost::bind(&C::f, this, ::_1));
    // soll ersetzt werden durch sowas wie 
    onClick().connect(boost::bind(g, &C::f, this, ::_1));
    // oder
    g(onClick(), &C::f, this, ::_1)); // so hab ich das zZ gemacht
    // wobei g eine freie Funktion ist, die u.a. f aufruft.
    // Der Aufruf sollte ähnlich einfach sein.
    

  • Mod

    Jockelx schrieb:

    Hallo,

    camper schrieb:

    Warum bestehts du darauf, dass der Parametertyp deiner Funktion mit dem Parametertypen des übergebenen Zeigers auf Memberfunktion übereinstimmen muss?

    es geht um das Problem

    Kurz und knapp:

    ...
    

    Das erklärt den Kontext, ich sehe allerdings nicht, dass die Frage damit beantwortet ist.



  • Dann verstehe ich deine Frage nicht.
    Ich 'bestehe' darauf, dass man den Typ im Aufruf nicht nochmal explizit angeben muss.



  • camper hat dir doch eh zwei Möglichkeiten gezeigt wie du es machen kannst. Was genau verstehst du denn daran nicht?

    @camper
    Gibt's in den neuen Standards echt keine "identity type function"?


  • Mod

    hustbaer schrieb:

    Gibt's in den neuen Standards echt keine "identity type function"?

    Nein. Für C++11 wurde std::identity vorgeschlagen (N1856) und aufgenommen. Allerdings war die ursprüngliche Motivation, nämlich template argument deduction für forward zu unterbinden (siehe 20.2.2 im verlinkten Paper), durch eine Überarbeitung von forward irrelevant geworden, weswegen es wieder gestrichen wurde.

    Überreste findet man bspw. in der libstdc++.



  • Danke, camper, funktioniert jetzt so wie ich wollte.



  • @Arcoth
    Danke.
    Schade eigentlich. Denn template argument deduction vermeiden kann man - wie man sieht - schon manchmal brauchen. Bzw. allgemein ist das so ein kleines dummes Hilfstemplate, wo es einfach wundert dass es das nicht gibt.


Anmelden zum Antworten