Soll die neue Funktionsdeklaration in C++0x die Alte vollständig ersetzen?



  • @asc:
    Diese Gedanken hatte ich über auto zwar auch schon, aber finde ich es bei Funktionsdeklarationen nicht unbedingt zutreffend.

    auto foo() -> int;
    

    finde ich offenbart den Rückgabetypen genau so schnell wie die klassische Variante



  • queer_boy schrieb:

    dann gibt es noch ein einsatzgebiet, wo du die neue funktionsdeklaration verwenden *musst*:

    template <Arithmetic A>
    auto twice (A&& a) -> decltype(A + A)
    {
      return a + a;
    }
    

    Frage dazu: kann mir jemand erklären warum folgendes SO problematisch zu parsen wäre dass man extra die komische auto syntax eingeführt hat:

    template <Arithmetic A>
    decltype(A + A) twice (A&& a)
    {
      return a + a;
    }
    

    ?
    Ich meine beim Parsen sollte ja alleine durch "decltype" klar sein dass es sich um einen Typ handelt, und das sollte ja wohl reichen ...? Nicht?
    Falls nicht, könnte mir wer mit halbwegs einfachen Worten erklären was an der Form so schwer/unpraktisch/unmöglich zu parsen ist, dass es sicht lohnt die Syntax dafür zu erweitern?

    @JustAnotherNoob:
    Genausowenig wie man heutzutage aus jeder Funktion ein Template macht wird man in ein paar Jahren für jede Funktion die neue Schreibweise verwenden. Bei Funktionen wo man es nicht braucht ist es einfach nur sinnloses "noise".



  • JustAnotherNoob schrieb:

    @asc:
    Diese Gedanken hatte ich über auto zwar auch schon, aber finde ich es bei Funktionsdeklarationen nicht unbedingt zutreffend.

    auto foo() -> int;
    

    finde ich offenbart den Rückgabetypen genau so schnell wie die klassische Variante

    Bei so kurzen Funktionsköpfen ja.
    So lange der "-> int" Teil noch am Schirm zu sehen ist geht es ja noch, bei meinen Programmen wäre das allerdings nicht immer der Fall...


  • Mod

    hustbaer schrieb:

    Frage dazu: kann mir jemand erklären warum folgendes SO problematisch zu parsen wäre dass man extra die komische auto syntax eingeführt hat:

    template <Arithmetic A>
    decltype(A + A) twice (A&& a)
    {
      return a + a;
    }
    

    ?
    Ich meine beim Parsen sollte ja alleine durch "decltype" klar sein dass es sich um einen Typ handelt, und das sollte ja wohl reichen ...? Nicht?

    Typen als solche sind keine Ausdrücke, sie an deren Stelle treten zu lassen, führt mit Sicherheit zu Mehrdeutigkeiten (A)(A) ?
    Die Semantik von x+x hängt aber im Allgemeinen davon ab, ob x ein lvalue oder rvalue ist (und möglicherweise auch ein konstanter Ausdruck - constexpr). A() als Ersatz macht Probleme, wenn A als T& deduziert wurde, und (A)0 geht dann auch nicht - es wird in jedem Falle sehr umständlich.



  • Und all dies nur aus der Unwilligkeit, ein paar neue Schlüsselwörter einzuführen. 😞

    Klar, ich verstehe, aus welchen Gründen das quasi unmöglich ist, aber es wirkt sich definitiv negativ auf die Sprache aus. All diese Probleme gäbe es nicht, wenn man endlich mal ein Funktionsdeklarations-Schlüsselwort eingeführt hätte.


  • Administrator

    Weiss zufällig einer, wie das eigentlich bei der Operator Überladung bei Funktoren aussehen wird?

    class CTest
    {
    public:
        auto operator ()() -> void
        { }
        // so?
    }
    

    Im übrigen gefällt mir die neue Funktionsdeklarationsyntax sehr. Schon nur wegen dem strukturellen, z.B:

    // Alt:
    char  first_function();
    short second_function();
    int   third_function();
    long  fourth_function();
    
    // Neu:
    auto first_function()  -> char;
    auto second_function() -> short;
    auto third_function()  -> int;
    auto fourth_function() -> long;
    

    Finde, dass man die neue Syntax deutlich besser lesen kann.

    @Konrad,
    Deine Aussage begreife ich jetzt nicht so recht. Das auto ist ja nicht nur für die Funktionsdeklaration da.

    Grüssli



  • Dravere schrieb:

    @Konrad,
    Deine Aussage begreife ich jetzt nicht so recht. Das auto ist ja nicht nur für die Funktionsdeklaration da.

    Schrieb ich auch nirgendwo, eher im Gegenteil. Es geht ja gerade darum, dass diese ganzen Probleme, die C++ sich hier aufhalst (siehe campers Erklärung) nur daher stammen, dass man kein eigenes Schlüsselwort für Funktionen einführen möchte. Stattdessen veranstaltet man lieber mal wieder Zeichensalat.

    Auch diese Lambdas/Closures. Da bekomme ich echt Würgreiz. Aber na ja. Man hat sich eben für diese Kompatibilitätsschiene entschieden.



  • Ich denke Konrad hätte sich eher sowas gewünscht wie func/sub/<anderes Schlüsselwort aussuchen>, statt auto, welches wieder je nach Kontext eine andere Bedeutung haben kann. Dieses Kontextbehaftete ist es ja letztlich auch, was es ziemlich schwierig macht, C++ zu parsen.

    sub my_func() -> int
    

  • Administrator

    Achso, jetzt versteh ich.
    Als Nicht-Compiler-Bauer habe ich ehrlich gesagt nichts dagegen. Im Gegenteil, ich finde sowas angenehm. Ich mag sogar Schlüsselwörter, welche je nach Fall etwas anderes bedeuten. Das finde ich eine sinnvolle Ausnutzung der Schlüsselwörter und nicht unnötiges dazu werfen. Aber darüber kann man natürlich geteilter Meinung sein.

    Ein Compiler-Bauer wird da natürlich stöhnen und die Sprache verfluchen, aber sind nicht auch von diesen welche im Komitee?
    Und naja, für die Anfänger mag es womöglich etwas verwirrend sein. Aber C++ war ja noch nie eine Anfängersprache und sollte sich auch nicht in diese Richtung entwickeln.

    Grüssli



  • Dravere schrieb:

    Und naja, für die Anfänger mag es womöglich etwas verwirrend sein. Aber C++ war ja noch nie eine Anfängersprache und sollte sich auch nicht in diese Richtung entwickeln.

    Nein, aber man sollte auch nicht eine Sprache unnötig verkomplizieren. Wenn man nachträglich Schlüsselwörter in eine Sprache einbaut die man benutzen müsste (Wie z.B. ein Schlüsselwort um Funktionen zu deklarieren), ist jeder gezwungen es zu verwenden und seinen Programmierstil zwangsweise anzupassen. Gegen Schlüsselwörter die die Sprache ergänzen, habe ich wiederum nichts.

    cu André



  • Dravere schrieb:

    ...Compiler-Bauer ... Anfänger ...

    Hi,

    also ich finde, man braucht weder Compilerbauer noch Anfänger zu sein, um bei Konstrukten mit zahlreichen (),const,[],&,*,<>, ... ins Grübeln zu kommen. Da gibt's schon Kombinationen, bei denen durch leichte Variation der Reihenfolge das Ganze gleich eine ganz andere Bedeutung bekommt.
    Da hätte man vllt. wirklich durch keywords ein wenig helfen können ... aber JETZT ist es natürlich nur noch selten möglich (mich wundert schon, dass jetzt noch eine andere Funktionsdeklaration eingeführt wird - finde ich aber gut).

    Gruß,

    Simon2.



  • camper schrieb:

    hustbaer schrieb:

    Frage dazu: kann mir jemand erklären warum folgendes SO problematisch zu parsen wäre dass man extra die komische auto syntax eingeführt hat:

    template <Arithmetic A>
    decltype(A + A) twice (A&& a)
    {
      return a + a;
    }
    

    ?
    Ich meine beim Parsen sollte ja alleine durch "decltype" klar sein dass es sich um einen Typ handelt, und das sollte ja wohl reichen ...? Nicht?

    Typen als solche sind keine Ausdrücke, sie an deren Stelle treten zu lassen, führt mit Sicherheit zu Mehrdeutigkeiten (A)(A) ?
    Die Semantik von x+x hängt aber im Allgemeinen davon ab, ob x ein lvalue oder rvalue ist (und möglicherweise auch ein konstanter Ausdruck - constexpr). A() als Ersatz macht Probleme, wenn A als T& deduziert wurde, und (A)0 geht dann auch nicht - es wird in jedem Falle sehr umständlich.

    Ok, nochmal. Wenn das OK ist:

    template <...>
    auto my_function(...) -> decltype(...)
    {
        // ...
    }
    

    ganz egal was die "..." jetzt hier sein müssen, wieso ist das dann nicht OK?:

    template <...>
    decltype(...) my_function(...)
    {
        // ...
    }
    

    Ob ich nun vorne auto stehen habe und hinten das decltype(...), oder gleich vorne das decltype(...) macht doch IMO keinen Unterschied.

    Oder gibt es Fälle wo man etwas mit der neuen Syntax machen kann was mit der alten nicht geht, wo die problematischen Stellen sich NICHT innerhalb eines decltype() befinden?



  • Naja, das ... ist ja gerade das relevante. Die Parameter werden normalerweise nach dem Rückgabetyp deklariert und sind deshalb für diesen noch nicht bekannt. Deshalb wird bei der neuen Variante der Rückgabetyp nach den Parametern deklariert, was Konstrukte wie

    template <typename A, typename B>
    auto add (const A& a, const B& b) -> decltype(a + b);
    

    ermöglicht. Wie camper schon sagte war das ursprüngliche Beispiel etwas irreführend.



  • @.filmor:
    OK, das ist mir schon klar.
    Ich verstehe bloss trotzdem noch nicht warum das ein Problem macht.
    In deinem Beispiel:

    template <typename A, typename B>
    auto add (const A& a, const B& b) -> decltype(a + b);
    

    Umgeschrieben auf die alte Variante:

    template <typename A, typename B>
    decltype(a + b) add (const A& a, const B& b);
    

    Wo ist das Problem?
    Klar, a und b sind "noch nicht bekannt". Nur... müssen die an der Stelle bekannt sein, damit der Parser wissen kann "das decltype(a + b) steht für einen Typen".

    Der Parser kann ja trotzdem schonmal sagen "da steht decltype(...), das muss ein Typ sein", und weitermachen.
    Wo das decltype endet sollte sich IMO auch bestimmen lassen ohne dass man schon wissen muss was a und b jeweils sind -- die Klammern müssen ja balanced sein, das sollte doch ausreichen.

    Ich meine C++ kann ja auch solche Dinge:

    class X
    {
    public:
        void foo()
        {
            std::vector<Y> v;
        }
    
        typedef int Y;
    };
    

    Klar, ich habe genau 0 Erfahrung und nur wenig theoretisches Wissen über Compilerbau oder allgemein Parser, aber ich kann mir einfach nicht vorstellen dass das so kompliziert zu parsen wäre.

    Deswegen meine Frage: gibt es da etwas woran ich nicht gedacht habe? Oder gibt es vielleicht mit diversen Dingen wie Funktionszeiger-Deklarationen oder templates oder nested types dann mögliche Konstrukte die sich wirklich nichtmehr parsen lassen?

    Ich hoffe du verstehst worauf ich hinaus will 😉

    Ich brauch' auch keine Erklärung hier wenn mir jmd. stattdessen ein Paper verlinken kann wo diese Problematik erklärt wird, also erklärt in welchen Fällen sich hier ein Problem ergeben würde und warum.



  • Davon Kapitel 3, da wird's erklärt. Die Namensauflösung wäre mit der „alten“ Syntax wohl nicht so dolle eindeutig und der Parser muss hüpfen.



  • asc schrieb:

    Ich seh das mit dem "auto" als zweischneidiges Schwert. Sicher hilft es bei komplexen Ausdrücken ungemein (Und dafür würde ich es auch verwenden), aber bei einfachen Ausdrücken (Sprich sowas wie std::string, int...) ist mir es lieber wenn ich den Typ auf einen Blick erfassen kann.

    Den wie heiß es so schön:

    Man liest Code häufiger, als man ihn schreibt.

    Andererseits: je leichter sich der Code ändern lässt, desto eher wirst du dies auch tun.

    Und so wirklich kann ich dein Argument auch nicht nachvollziehen, bzw. sehe nicht dass das so dramatisch ist wie du dir ausmalst. Der Typ ist doch zumeist entweder relativ irrelevant (ggf. ist es sogar hinderlich einen konkreten Typ angeben zu müssen), oder er geht mehr oder weniger eindeutig aus der Initialisierung und/oder dem Bezeichner hervor.



  • Ok, danke. Geht also wirklich hauptsächlich darum dass es kompliziert (aber nicht unmöglich) zu implementieren wäre. Und halt dass die "neue" Syntax für andere Dinge wie Funktionszeiger etc. auch ganz schick (und leichter lesbar) ist.
    Soll mir auch Recht sein 🙂



  • 'f schrieb:

    ...

    Man liest Code häufiger, als man ihn schreibt.

    Andererseits: je leichter sich der Code ändern lässt, desto eher wirst du dies auch tun....

    Naja, aber Probleme beim Ändern des Codes sind üblicherweise Folge von Problemen beim Lesen des Codes (sprich: schlecht strukturierter Code - sei es nun Syntax oder Design).
    Mir geht es jedenfalls so: Wenn ich schnell verstanden habe, was ein Programm tut, habe ich fast nie Probleme bei Codeänderungen (Ausnahme: Da, wo mit der Änderung das ursprüngliche Design gebrochen werden soll).

    Gruß,

    Simon2.


Anmelden zum Antworten