Funktionszeiger



  • Hallo.

    Ich probiere gerade ein paar Spielereien mit Templates und Funktionszeigern aus und habe zwei Probleme.

    template<typename T>
    void f(T)
    {
    }
    
    void g();
    
    int main()
    {
    	f(g);
    }
    

    Dieser Code erzeugt einen Linker-Fehler. Meiner Meinung nach ungerechtfertigt. Behalte ich recht?

    2. Ich weiss, dass ich die korrekte Überladung einer Funktion mit einem expliziten Cast des Zeigers wählen kann. Beispielsweise:

    std::cout << f(static_cast<float(*)(char)>(g));
    

    Geht das auch irgendwie ohne dass ich den Rückgabetypen angeben muss? Der gehört ja schliesslich nicht zur Signatur der Funktion.

    Gruss.



  • Nein, du hast unrecht.
    Du brauchst die Definition der Funktion g, damit deren Adresse als Template Argument übergeben werden kann, selbst wenn du die Funktion nicht aufrufst.


  • Mod

    Behalte ich recht?

    Nein - es gibt einen odr-use von g . Daher muss g definiert sein. Clang ist nicht standardkonform.

    Zu deinem anderen Problem:

    void g(int, long long, float) {}
    void g(char, long, double) {}
    
    template <typename T>
    struct identity
    {  using type = T;  };
    
    template <typename... T>
    struct deduce_impl
    {
    	template <typename R, typename... Superfluent>
    	static typename identity<R(*)(T..., Superfluent...)>::type from( R(*f)(T..., Superfluent...) )
    	{
    		return f;
    	}
    };
    
    template <typename Call>
    void bar(Call){}
    
    int main()
    {
    	bar( deduce_impl<char>::from(g) );
    }
    

    Kannst du in ein Makro packen.



  • Arcoth, mal eine Frage: Wieso identity?
    Tuts nicht einfach R(*)(T..., Superfluent...) als return type direkt?


  • Mod

    Tuts nicht einfach R(*)(T..., Superfluent...) als return type direkt?

    Nö, leider nicht.

    Mir fällt aber sowieso gerade auf dass das Unsinn ist.

    template <typename R, typename... Superfluent>
        static auto from( R(*f)(T..., Superfluent...) ) -> decltype(f)
        {
            return f;
        }
    

  • Mod

    Arcoth schrieb:

    Behalte ich recht?

    Nein - es gibt einen odr-use von g . Daher muss g definiert sein. Clang ist nicht standardkonform.

    ODR-Verletzungen bedürfen in der Regel keiner Diagnose...



  • Hallo.

    Erstens erscheint mir nun völlig logisch, da hätte ich auch selbst drauf kommen können. 🙄

    Arcoth schrieb:

    Clang ist nicht standardkonform.

    Ebenso GCC 4.8.1

    Zu zweitens:
    Danke Moderator Arcoth, super Lösung. Ich denke, mit einer knackigen kurzen Bezeichnung ist nicht einmal ein Makro nötig.

    Schönen Tag noch.


  • Mod

    Arcoth schrieb:

    Clang ist nicht standardkonform.

    Nochmal selbst getested. clang steigt mit einem Linkerfehler aus. Was soll daran nicht standardkonform sein? Der Compiler kann sich ja gar nicht beschweren, schließlich könnte g ja auch in einer anderen ÜE definiert sein.


  • Mod

    clang steigt mit einem Linkerfehler aus

    Nicht bei mir.

    void g(int, long long, float);
    void g(char, long, double);
    
    template <typename T>
    struct identity
    {  using type = T;  };
    
    template <typename... T>
    struct deduce_impl
    {
    	template <typename R, typename... Superfluent>
    	static auto from( R(*f)(T..., Superfluent...) ) -> decltype(f)
    	{
    		return f;
    	}
    };
    
    template <typename Call>
    void bar(Call){}
    
    int main()
    {
    	bar( deduce_impl<char>::from(g) );
    }
    
    clang++ -O3 -std=c++1y ...
    

    Kompiliert (und linkt) einwandfrei.

    Liegt wohl am Optimierungsflag -O3, dasselbe Ergebnis mit GCC (4.9)... hihi, mein Fehler. Entschuldige. 🙂

    ODR-Verletzungen bedürfen in der Regel keiner Diagnose...

    Ja, aber laufen kann das Programm wohl nicht, oder?



  • VS2013 sagt sowohl in Debug als auch in Release

    error LNK2001: unresolved external symbol "void __cdecl g(char,long,double)"

    Ich schwöre ich habe keine Drogen genommen, aber da steht Arcoth Moderator. 😮



  • nwp3 schrieb:

    Ich schwöre ich habe keine Drogen genommen, aber da steht Arcoth Moderator. 😮

    http://www.c-plusplus.net/forum/p2406401#2406401

    @Arcoth:
    Mir ist klar, dass die Syntax dafür beschissen ist, aber gibt es nocht einen anderen Grund? Oder ist das einfach nur für eine schönere Syntax?



  • nwp3 schrieb:

    VS2013 sagt sowohl in Debug als auch in Release

    error LNK2001: unresolved external symbol "void __cdecl g(char,long,double)"

    Ja, mit VS2013 hab ich es auch ursprünglich getestet und den Fehler erhalten.

    nwp3 schrieb:

    Ich schwöre ich habe keine Drogen genommen, aber da steht Arcoth Moderator. 😮

    Bei mir auch, und? 😕
    Vielleicht ist es ein wenig falsch 'rübergekommen. Das war nicht ironisch gemeint oder so sondern soll in leichter Form zur Erkürung zum Moderator gratulieren.


Log in to reply