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



  • Bashar schrieb:

    Es wird sich nichts verändern, es wird aber was dazukommen. Dazu liest du am besten diesen Artikel:
    http://www.c-plusplus.net/forum/viewtopic-var-t-is-204654.html
    (Abschnitt 1.5)

    Das was Shade da fabriziert hat ist übrigens ein Lambda-Ausdruck, das ist nicht dasselbe wie eine Funktionsdeklaration.

    was mich nur wundert, und was wahrscheinlich auch der grund war weshalb shade diese syntax gepostet hat ist, dass die englische wikipedia die auto syntax nichtmehr enthält:

    http://en.wikipedia.org/wiki/C%2B%2B0x#Unified_function_syntax

    aus dem Artikel:

    struct SomeStruct
    {
      []FuncName(int x, int y) -> int;
    }
    
    []SomeStruct::FuncName(int x, int y) -> int
    {
      return x + y;
    }
    


  • Bashar schrieb:

    Das was Shade da fabriziert hat ist übrigens ein Lambda-Ausdruck, das ist nicht dasselbe wie eine Funktionsdeklaration.

    ah, ja sorry.
    auto war es hier ja.

    hab mich lediglich auf das -> type
    am ende konzentriert 😕



  • queer_boy schrieb:

    bei manchen rückgabetypen wird es jedoch sicher einfacher sein, die neue funktionsdeklaration zu verwenden, z.b. bei komplexen rückgabetypen (tuples, funktionszeiger)

    *g* davon kann ich ein Lied singen:

    template <typename TChar, typename TSpec, typename TPos>
    inline typename Iterator<typename Host<StringSet<TChar, Packed<TSpec> > >::Type>::Type
    hostIter(StringSet<TChar, Packed<TSpec> > const& strs, TPos pos) {
        return begin(host(strs[pos]));
    }
    

    Da ist 'auto' natürlich praktisch.

    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;
    }
    

    Müsste es hier nicht 'decltype(a + a)' heißen?



  • Konrad Rudolph schrieb:

    queer_boy schrieb:

    bei manchen rückgabetypen wird es jedoch sicher einfacher sein, die neue funktionsdeklaration zu verwenden, z.b. bei komplexen rückgabetypen (tuples, funktionszeiger)

    *g* davon kann ich ein Lied singen:

    template <typename TChar, typename TSpec, typename TPos>
    inline typename Iterator<typename Host<StringSet<TChar, Packed<TSpec> > >::Type>::Type
    hostIter(StringSet<TChar, Packed<TSpec> > const& strs, TPos pos) {
        return begin(host(strs[pos]));
    }
    

    ...

    😃 👍

    Allerdings habe ich mir derzeit schon einen "Skip-Blick" angewöhnt:

    • Erstmal die '(' suchen,
    • dann den Bezeichner davor - dann weiß man schonmal, wie die Funktion heißt und vermutlich machen soll (oder ob der A*** einen FunkPtr zurückgeben will 😉 )
    • und von da aus nach rechts die Parameter ...
    • und nach links den Rückgabetypen.

    Das Vorgehen werde ich nun ein wenig modifizieren müssen.
    Ich bin auf jeden Fall schon gespannt, wie/wo sich die "->-Schreibweise" durchsetzen wird ... nur da, wo das andere zu kompliziert ist ... oder evtl. auf breiterer Basis.

    Gruß,

    Simon2.



  • Shade Of Mine schrieb:

    Bashar schrieb:

    Das was Shade da fabriziert hat ist übrigens ein Lambda-Ausdruck, das ist nicht dasselbe wie eine Funktionsdeklaration.

    ah, ja sorry.
    auto war es hier ja.

    Naja, wenn die Wiki-Seite stimmt und ich sie auf die Schnelle richtig verstanden habe, wird man wohl Funktionen auch als benannte Lambda-Ausdrücke (ist das nicht irgendwo ein Widerspruch? 🙂 ) definieren können.



  • Nunja, aber wenn die alte leglich kürzer zu schreiben ist, man die neue aber dennoch manchmal braucht, fände ich es wesentlich konsistenter durchgängig die neue zu verwenden, oder etwa nicht?



  • JustAnotherNoob schrieb:

    Nunja, aber wenn die alte leglich kürzer zu schreiben ist, man die neue aber dennoch manchmal braucht, fände ich es wesentlich konsistenter durchgängig die neue zu verwenden, oder etwa nicht?

    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.

    So werde ich wohl auch in Zukunft dann vorgehen: Für einfache Ausdrücke die alte Schreibweise verwenden, für komplexe siegt imho die Kürze über den Informationsgehalt, da man bei solchen Ausdrücken eh letzteres nicht gegeben ist (Komplexe Ausdrücke sind meist sowieso nicht mit einen Blick zu erfassen).

    cu André



  • Bashar schrieb:

    Naja, wenn die Wiki-Seite stimmt und ich sie auf die Schnelle richtig verstanden habe, wird man wohl Funktionen auch als benannte Lambda-Ausdrücke (ist das nicht irgendwo ein Widerspruch? 🙂 ) definieren können.

    als ich letztens meinen artikel auf die neue lambda-schreibweise upgedatet habe, bin ich tatsächlich auf ein solches proposal gestoßen. ich weiß zwar nicht mehr genau warum, aber damals dachte ich mir, dass das wohl nicht durchkommt (zu unausgereift vielleicht, und außerdem könnte der neue standard ja jetzt seit samstag schon feature complete sein, und wenn das ein neues proposal war...)

    aber da müsste ich jetzt nochmal durch die proposal schauen, was mir im moment etwas zu mühsam ist. lieber den neuen draft abwarten.



  • @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?


Anmelden zum Antworten