Funktion in Funktion definieren



  • Ich bin über dieses kleine Programm gestolpert. Aber wenn ich das jetzt mit dem G++ kompiliere funktioniert es nicht. mit dem GCC schon. Gibt es nicht etwas ähnliches in C++?

    #include <stdio.h>
    
    int main()
    {
    	int funcinfunc()
    	{
    		return 1;
    	}
    	if(funcinfunc())
    		printf("TRUE\n");
    
    }
    


  • Das scheint eine Grauzone der Compiler-Hersteller zu sein.

    Genormt in C und C++ ist die separate Deklaration von Funktions-Prototypen bereits vor deren Einsatz, damit der Compiler diese sauber erkennen kann.
    Selbst wenn dein Compiler so etwas zulässt, tust du dir keinen grossen Gefallen und kannst nicht erwarten, dass andere Compiler das so mitmachen!



  • Ich sehe auch den Vorteil solcher Funktionsdefinitionen nicht.



  • Hmmm, keine Ahnung, wie's mit Standard aussieht, aber MSVC unterstützt sowas:

    int main()
    {
        struct func {
           int operator() () { return 1; }
        } funcinfunc;
    
        cout << funcinfunc() << endl;
    }
    

    Und mit C++0x natürlich per Lambda-Funktion:

    int main()
    {
        auto funcinfunc = [] () { return 1; };
    
        cout << funcinfunc() << endl;
    }
    

  • Mod

    Der Standard erlaubt keine Funktionen in anderen Funktionen, sowohl in C als auch in C++. Warum dies jedoch als Compilerfeature in der C Variante vom GCC existiert und nicht in der C++ Variante ist mir ein Rätsel (ich kann diese Beobachtung bestätigen). Vielleicht irgendeine Schwierigkeit beim Parsen von C++ die mir nicht einfallen mag? Oder die beiden Compilerteile werden einfach in unterschiedlichen Zweigen entwickelt.



  • _matze schrieb:

    Ich sehe auch den Vorteil solcher Funktionsdefinitionen nicht.

    Ich verstehe generell nicht, weshalb solche Dinge wie eine lokale Struktur so vorteilhaft sein sollen. Die Verfechter argumentieren meist mit grösserer Lokalität. Aber ist es wirklich so ein Unterschied, ob es jetzt

    void Helper(int x)
    {
       // tu was
    }
    
    void Function()
    {
        Helper(7);
    }
    

    oder

    void Function()
    {
        struct
        {
            void operator(int x)
            {
                // tu was
            }
        } Helper;
    
       Helper(7);
    }
    

    heisst? Klar hat man vielleicht noch ein wenig Code darum herum, aber lustigerweise sind die Verfechter oft auch Kurz-Funktionen-Fanatiker. 😉

    Den anderen Punkt sehe ich im Sichtbarkeitsbereich. Doch da solche Konstrukte ohnehin meist in .cpp-Dateien vorkommen, sehe ich auch hier kein grosses Problem, wenn ein paar nachfolgende Funktionen prinzipiell den Helper verwenden könnten. Hingegen entsteht etwas mehr Code und mir persönlich ist die Semantik weniger schnell klar als bei einer Extra-Funktion.

    Lambda-Funktionen hingegen finde ich echt praktisch, vor allem da sie eine kompakte Syntax besitzen und direkt in einem Ausdruck definiert werden können.



  • Es ist in Funktionsvorlagen ein Unterschied.

    Allerdings kommt man auch ganz gut ohne zurecht. Ich helfe mir in solchen Fällen in aller Regel entweder mit einem namespace impl o.ä. oder dem namenlosen namespace.



  • seldon schrieb:

    Es ist in Funktionsvorlagen ein Unterschied.

    Templates? Abgesehen von meinem deutschen Visual Studio habe ich schon lange niemanden mehr von "Vorlagen" reden hören. Gleich wie "Verweise" statt "Referenzen". Soll kein Vorwurf sein, ist mir nur aufgefallen... 😉

    Zum Thema: Bei Funktionstemplates ist es insofern ein Unterschied, als die externe HelperFunktion eventuell nochmals Template-Parameter braucht. Was oft aber auch noch im Rahmen liegt... Meintest du das?

    Wenn es geht (d.h. keine funktionalen Algorithmen), schreibe ich den Code auch oft einfach inline in die Funktion. Vor allem wenn die Indirektion für mich keinen Vorteil hat, nehme ich lieber eine längere als eine fragmentierte Funktion.

    seldon schrieb:

    Allerdings kommt man auch ganz gut ohne zurecht. Ich helfe mir in solchen Fällen in aller Regel entweder mit einem namespace impl o.ä. oder dem namenlosen namespace.

    Genau so handhabe ich das auch. Oft habe ich einen namespace detail , der ist besonders in Template-Implementierungsdateien praktisch, damit der umliegende Namensraum sauber bleibt.



  • Naja, "Templatefunktion" ist schlicht falsch, und "Funktionstemplate" klingt irgendwie komisch. Außerdem macht "Funktionsvorlage" sofort klar, worum es sich bei Funktionsvorlagen handelt.

    Was ich meinte ist, dass lokale Funktionen in Funktionsvorlagen (und inline-Funktionen, wo ich gerade daran denke) eine Verschmutzung des umgebenden Namensraums mit Symbolen, die nicht zum API gehören, vermeiden helfen könnten. Natürlich ist es völlig akzeptabel (und gängige Praxis), solche Symbole in einen Namensraum auszulagern, dessen Name es völlig klar macht, dass sie nicht zum API gehören, aber ich habe durchaus Verständnis für den Wunsch, auch das zu vermeiden. Jedenfalls macht es da aber einen Unterschied.


Anmelden zum Antworten