Soll die neue Funktionsdeklaration in C++0x die Alte vollständig ersetzen?
-
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...
-
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.
-
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
-
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.