Trailing Return Types Everywhere


  • Mod

    @Finnegan sagte in Arraygröße bestimmen lassen:

    Und inwiefern auto main() -> int eine stilistische Verbesserung sein soll, das musst Du mal erklaeren...

    Interessant, dass du dich daran stösst ... das kann ich erklären: Die auto f() -> type-Syntax hat den grossen Vorteil, dass alle Funktionsnamen in der selben Editorspalte beginnen. Die Namen sind m.E. die wichtigste Information, und das konsequent zu machen macht meiner Meinung nach den Code besser lesbar. Spätestens dann, wenn es umfangreicher wird. Eine Ausnahme mache ich bei void, weil auto f() -> void finde selbst ich dann auch ein wenig affig

    Am besten noch #define fn auto? 🤨 Ich meine, dass man sich das gar nicht erst aneignen braucht, weil es im professionellen Kontext niemals einen Style Guide bestehen wuerde. Der Zweck von trailing return types liegt eigentlich primaer beim unqualified name lookup, und bei Typen mit langen Namen, und ggf. wenn der Rueckgabetyp sonst eine Verschachtelung des Deklarators erfordern wuerde, bspw. ein Funktionszeiger.
    Es bei int einzusetzen mutet, wie Du bereits angedeutet hast, affig an. Es kommt (fuer mich) rueber als wuerde der Autor uebereifrig und fast unbedacht neue Features in den Code klatschen, damit er interessanter ausschaut, oder um ihm eine moderne Aesthetik zu verleihen.



  • @Columbo sagte in Arraygröße bestimmen lassen:

    @Finnegan sagte in Arraygröße bestimmen lassen:

    Und inwiefern auto main() -> int eine stilistische Verbesserung sein soll, das musst Du mal erklaeren...

    Interessant, dass du dich daran stösst ... das kann ich erklären: Die auto f() -> type-Syntax hat den grossen Vorteil, dass alle Funktionsnamen in der selben Editorspalte beginnen. Die Namen sind m.E. die wichtigste Information, und das konsequent zu machen macht meiner Meinung nach den Code besser lesbar. Spätestens dann, wenn es umfangreicher wird. Eine Ausnahme mache ich bei void, weil auto f() -> void finde selbst ich dann auch ein wenig affig

    Am besten noch #define fn auto? 🤨 Ich meine, dass man sich das gar nicht erst aneignen braucht, weil es im professionellen Kontext niemals einen Style Guide bestehen wuerde. Der Zweck von trailing return types liegt eigentlich primaer beim unqualified name lookup, und bei Typen mit langen Namen, und ggf. wenn der Rueckgabetyp sonst eine Verschachtelung des Deklarators erfordern wuerde, bspw. ein Funktionszeiger.

    Ich habe dir meine Motivation erklärt, stattdessen argumentierst du lediglich via Apell an Autorität ("würde im professionellen Kontext niemals bestehen"), machst dich darüber lustig ("#define fn auto") und legst dar, wofür es ursprünglich eingeführt wurde (nichtsdetotrotz ist es auch für simple Typen eine gültige, alternative Syntax!). "Professionell" geht meiner Meninug nach anders - da wird für und wider mit Argumenten ausdiskutiert.

    Wie du sehen kannst, reagiere ich nicht gut auf solche Null-Argumente. Ich würde stattdessen lieber etwas lesen wie "ja, man findet die Funktionsnamen zwar schnell, wenn man mit den Augen die Editorspalte scannt, aber da zusätzliche auto ist extra Schreibarbeit" ... oder was ähnliches.

    Es bei int einzusetzen mutet, wie Du bereits angedeutet hast, affig an. Es kommt (fuer mich) rueber als wuerde der Autor uebereifrig und fast unbedacht neue Features in den Code klatschen, damit er interessanter ausschaut, oder um ihm eine moderne Aesthetik zu verleihen.

    Ich finde die Ästetik tatsächlich ansprechend - und zwar unabhängig davon, ob es "modern" ist oder nicht:

    std::vector<int> f1(int a, int b);
    int f2(int a, int b);
    std::pair<std::string, int> f3(int a, int b);
    void f4();
    

    vs.

    auto f1(int a, int b) -> std::vector<int>;
    auto f2(int a, int b) -> int;
    auto f3(int a, int b) -> std::pair<std::string, int>;
    void f4();
    

    Das führt m.E. zu schönerem Code - warum also nicht, wenn es eine gültige alternative Schreibweise für Return Types ist?

    Oder kommt jetzt "das ist Scheisse weil - das haben wir schon immer so gemacht?" 😡


  • Mod

    @Finnegan sagte in Arraygröße bestimmen lassen:

    Ich habe dir meine Motivation erklärt, stattdessen argumentierst du lediglich via Apell an Autorität ("würde im professionellen Kontext niemals bestehen"), machst dich darüber lustig ("#define fn auto") und legst dar, wofür es ursprünglich eingeführt wurde (nichtsdetotrotz ist es auch für simple Typen eine gültige, alternative Syntax!). "Professionell" geht meiner Meninug nach anders - da wird für und wider mit Argumenten ausdiskutiert.

    Mein vollkommen objektives Argument war, dass sich diesen Stil anzueignen einen Nachteil mit sich bringt, weil Style Guides von Unternehmen wie bspw. Google es nicht erlauben:

    Use trailing return types only where using the ordinary syntax (leading return types) is impractical or much less readable.

    ... und man deshalb

    • wenn man anfaengt in irgendeinem Projekt mitzuarbeiten, sei es Open Source oder Corporate, es sich sowieso abtrainieren muss (-> Lernaufwand)
    • man damit auch andere Leser allgemein irritiert, so wie z.B. mich, und wahrscheinlich die allermeisten Programmierer

    Es ist analog zur Debatte ob man && oder and schreiben soll: Ich wuerde subjektiv argumentieren, and/or liest sich irgendwie huebscher, und hat auch nicht wirklich irgendwelche Nachteile, aber trotzdem waere es suboptimal es irgendwo einzusetzen, weil es einfach nicht der modus vivendi der Industrie ist, und folglich die Lesbarkeit darunter deutlich leidet.

    Das ist natuerlich kein Argument, dass rein von der Sprache selbst handelt. Aber als C++ Coder argumentiert man nie "ueber die Sprache eo ipso", weil ihr Einsatz nicht Selbstzweck ist, oder irgendein esoterisches Kunstwerk; sondern er erschafft im Idealfall ein Program, dass andere leicht erweitern und warten koennen. Und das setzt voraus, dass die Wahl der Stilistik nicht allzu exotisch ist. Im Umkehrschluss: Je mimetischer der Stil, desto hilfreicher ist er den Lesern. Wo es also keinen triftigen Grund gibt davon abzuweichen, sollte man sich daran halten.

    Andere Argumente:

    • Du erwaehnst, dass die Funktionsnamen damit auf die gleiche Spalte ausgerichtet werden. Das ist aber nur hilfreich, wenn mehrere Deklarationen unmittelbar hintereinander stehen. main() wird immer definiert, hier zieht das also nicht. I.A. ist es bzgl. Lesbarkeit egal ob ein Name auf der 5ten oder 12ten Spalte steht, Hauptsache es ist nicht die 40ste.
    • Wenn wir von Einheitlichkeit sprechen, dann wird Einheitlichkeit ueber viele Projekte hin mEn. mehr wiegen, als Einheitlichkeit innerhalb eines Projekts. Nur weil Du irgendwo trailing return types brauchst, muss man sie nicht ueberall einsetzen.

    Wie du sehen kannst, reagiere ich nicht gut auf solche Null-Argumente.

    Ich hatte zuerst gelesen "ich reagierre nicht auf solche Null-Argumente", und wollte schon widersprechen, als ich das "gut" entdeckt habe 😃



  • @Finnegan: Bei dir sieht es aber nur so harmonisch aus, weil die Funktionsnamen und Parameter (Typen + Namen) gleich lang sind. In den meisten Fällen ist der Code dann m.E. noch schlechter (unruhiger) zu lesen.

    Es gibt auch noch die Möglichkeit den Rückgabetyp in einer extra Zeile voran zu stellen:

    std::vector<int>
    f1(int a, int b);
    
    int
    f2(int a, int b);
    
    // alternativ mit Einrückung (zumindestens bei Deklarationen)
    std::pair<std::string, int>
      f3(int a, int b);
    
    void
      f4();
    

    Mit eurer Diskussion habt ihr aber wohl @Hawaiihemd verschreckt (ihr solltet euch mal in die Situation eines C++ Anfängers zurückversetzen, der gerade die ersten Kapitel eines C++ Buchs durchgelesen hat).


  • Mod

    @Th69 Danke fuer den Hinweis, diese Diskussion ist schon hart OT und ist deshalb jetzt separiert.



  • @Columbo sagte in Trailing Return Types Everywhere:

    Mein vollkommen objektives Argument war, dass sich diesen Stil anzueignen einen Nachteil mit sich bringt, weil Style Guides von Unternehmen wie bspw. Google es nicht erlauben:

    Nein, du hast von "im professionellen Kontext" geschrieben, nicht von google. Alle Unternehmen, die nicht so einen strengen Style-Guide haben, arbeiten also nicht professionell? Insbesondere sagst du damit auch, dass @Finnegan nicht professionell arbeitet. Sind für dich nur Großkonzerne professionell?

    Und wenn du mit Style-Guides argumentierst, dann darfst du auch viele andere Dinge nicht nutzen. Firmen haben auch unterschiedliche Guides. Das Argument "Konsistenz über das gesamte Projekt / über mehrere Projekte" verstehe ich, aber es fängt schon mit unterschiedlichen Naming- und Whitespace-Konventionen an, dass es das nicht gibt.


  • Mod

    @wob sagte in Trailing Return Types Everywhere:

    @Columbo sagte in Trailing Return Types Everywhere:

    Mein vollkommen objektives Argument war, dass sich diesen Stil anzueignen einen Nachteil mit sich bringt, weil Style Guides von Unternehmen wie bspw. Google es nicht erlauben:

    Nein, du hast von "im professionellen Kontext" geschrieben, nicht von google.

    Soll ich "bspw." ausschreiben, damit Du verstehst, dass ich damit nur eine von vielen Instanzen heranziehe, um das Gesagte zu bekraeftigen?

    Alle Unternehmen, die nicht so einen strengen Style-Guide haben, arbeiten also nicht professionell?

    Lass den Strohmann stecken. Es gibt fuer jede Regel Ausnahmen. Die meisten Unternehmen unterwerfen den Code einem mehr oder weniger rigorosen Stil. Das ist nicht kontrovers. auto main() -> int zu verbieten ist nicht wirklich streng, weil es mehr Zeichen erfordert und quasi keinen Vorteil hat (den, auf den sich @Finnegan bezog, trifft hier sowieso nicht zu und auch sonst bestenfalls occasionally).

    Insbesondere sagst du damit auch, dass @Finnegan nicht professionell arbeitet. Sind für dich nur Großkonzerne professionell?

    Noch mehr Strohmaenner. Wenn man der Dialektik nicht faehig ist, dann nuetzt es nicht, so zu tun als ob!

    Und wenn du mit Style-Guides argumentierst, dann darfst du auch viele andere Dinge nicht nutzen.

    Das soll ein Argument sein, um sich gar nicht erst zu bemuehen, dem gemeinsamen Nenner guter Stile zu folgen?

    Das Argument "Konsistenz über das gesamte Projekt / über mehrere Projekte" verstehe ich, aber es fängt schon mit unterschiedlichen Naming- und Whitespace-Konventionen an, dass es das nicht gibt.

    Genau, also am Besten drei Whitespaces pro Block und kein Whitespace zwischen Operator und Operanden. Weil man kann ja eh nicht jeden gluecklich machen. Oder vielleicht probiert man einfach mal gesunden Verstand walten zu lassen, dann kommt man auch auf einen guten Stil, den die meisten fluessig lesen koennen. Dann waeren wir wieder am Anfang...

    Addendum: Man schaue sich einfach mal die beliebtesten Kommentare in diesem SO Post an: https://stackoverflow.com/questions/21085446/what-is-the-meaning-of-auto-main-int
    "I personally find auto main() -> int a horrible idea." "and what is the advantage of declaring main this way? - I'm not claiming that there is an advantage."



  • @Columbo sagte in Trailing Return Types Everywhere:

    Mein vollkommen objektives Argument war,

    Bei "vollkommen" möchte ich widersprechen. Gerade bei der Sache mit dem Rust-Seitenhieb mit dem fn-Makro und Formulierungen wie "unbedacht neue Features in den Code klatschen" schimmert schon eine gewisse Abneigug gegen diese Schreibweise durch.

    Ich vermute, das liegt daran, dass das für dich ein eher "exotisches" Sprachfeature zu sein scheint:

    Und das setzt voraus, dass die Wahl der Stilistik nicht allzu exotisch ist.

    Meine Perspektive drauf ist eher neutral: Ich sehe hier lediglich zwei mindestens gleichwertige alternative Schreibweisen, von denen eine sogar noch ein wenig mächtiger ist (z.B. bei von template-parametern abhängigen Rückgabetypen).

    Oder habe ich hier etwas grundlegendes missverstanden? Gibt es etwa irgendeinen einen semantischen Unterschied zwischen int f() und auto f() -> int?

    Für mich ist diese Diskussion daher eher wie East Const vs West Const oder int* x vs int *x, also eigentlich müßig. Jeder Entwickler und jedes Team hat seine Präferenzen und auch ein angehender Entwickler muss ohnehin lernen, mit beiden Varianten umzugehen und je nach Projekt diese auch zu schreiben - und sei es nur weil der Trailing return Type eben manchmal notwendig ist. Der einzige Grund, weshalb es als nicht "normal" empfunden wird ist, dass man es eben eher selten sieht. Würde das öfter verwendet, gäbe es diese Disussion wahrscheinlich nicht in dieser Form - eher auf West/East-Const-Niveau. Und das, obwohl sich an den objektiven Argumenten immer noch die selben wären.

    dass sich diesen Stil anzueignen einen Nachteil mit sich bringt, weil Style Guides von Unternehmen wie bspw. Google es nicht erlauben:

    Use trailing return types only where using the ordinary syntax (leading return types) is impractical or much less readable.

    ... und man deshalb

    • wenn man anfaengt in irgendeinem Projekt mitzuarbeiten, sei es Open Source oder Corporate, es sich sowieso abtrainieren muss (-> Lernaufwand)

    Diese Anpassungsfähigkeit wird immer erforderlich sein. Im besonderen gilt das für C++, das wohl von allen Sprachen am weitesten von einem sprachübergreifend etablierten Code-Stil entfernt ist. Auch ein Anfänger sollte das lernen - aber ich stimme zu, dass das besser erst dann passieren sollte, wenn die Grundlagen sitzen. Und auch gerade bei Open Source ist die Wahrscheinlichkeit gross, dass man mit sehr vielen unterchiedlichen Stilen zurecht kommen muss - sei es durch nicht selten laxere Stilvorgaben oder eben durch viele kleine Beiträge zu sehr unterschiedlichen Projekten.

    Ich mag da aber auch eine etwa spezielle Sichtweise haben, da ich regelmässig mit sehr unterschiedlichem Code aus verscheidenen Projekten konftrontiert bin. Wenn ich seit vielen Jahren immer nur den Code des selbens Projekt in einem einheitlichen Stil gesehen hätte, würden mir Abweichungen wahrscheinlich auch erstmal unangenehm ins Auge fallen.

    Wenn wir von Einheitlichkeit sprechen, dann wird Einheitlichkeit ueber viele Projekte hin mEn. mehr wiegen, als Einheitlichkeit innerhalb eines Projekts. Nur weil Du irgendwo trailing return types brauchst, muss man sie nicht ueberall einsetzen.

    Globale Einheitlichkeit in C++ halte ich für eine Illusion und beschränke mich darauf mir für eigene Projekte einen Stil zu entwickeln, den ich als sinnvoll erachte und mich ansonsten an das Team anzupassen, in dem ich mitarbeite.

    Das heisst aber nicht, dass ich alles was in diesen Style Guides steht gut finden muss. In denen steht nämlich nicht selten auch eine Menge fragwürdiges Zeug. Gut und richtig, wenn man sich in einem Unternehmen oder für ein Projekt auf einen einheitlichen Stil geeinigt hat, das ist aber kein Grund auch Dinge, bei denen man gute Argumente dagegen hat in Zement zu gießen und überall anzuwenden - nur weil andere das auch tun und man das "schon immer so gemacht hat". Diese Mentaltität ist meiner Meinung mit einer der Gründe dafür, weshalb im C++-Umfeld "C mit Klassen" oder C++98-Stil immer noch so prävalent sind.

    • man damit auch andere Leser allgemein irritiert, so wie z.B. mich, und wahrscheinlich die allermeisten Programmierer

    Aus der Perspektive, die Trailing Return Types eben als "exotisches" Feature sieht, ist die Irritation natürlich nachvollziehbar. Du solltest aber auch versuchen meine Sichtweise zu verstehen, dass es für mich eben ist, wie wo das const oder wo der Pointer-Stern steht. Mit dieser Wahrnehmung geht es dann wirklich nur noch darum, was man als besser lesbar empfindet.

    Es ist analog zur Debatte ob man && oder and schreiben soll: Ich wuerde subjektiv argumentieren, and/or liest sich irgendwie huebscher, und hat auch nicht wirklich irgendwelche Nachteile, aber trotzdem waere es suboptimal es irgendwo einzusetzen, weil es einfach nicht der modus vivendi der Industrie ist, und folglich die Lesbarkeit darunter deutlich leidet.

    Ich weiss das das nur ein Beispiel für "gleichwertige Schreibweisen" ist (sind and/or nicht schon deprecated oder trügt mich meine Erinnerung?) dennoch ein paar Argumente:

    &&/ || sind gleich lang und führen nicht dazu, dass eine Zeile länger oder kürzer wird, wenn man das eine durch das andere ersetzt. Den größten Vorzeil sehe ich allerdings in der Verwendung von Symbolen vs Buchstaben, weshalb diese Operatoren für mich deutlicher deutlicher ins Auge stechen. and und or könnten auf en ersten Blick auch Identifier sein. Daher finde ich einen Ausdruck, der &&/|| verwendet leichter zu lesen. In Sprachen mit and/or tendiere ich daher sogar dazu, diese Operatoren groß zu schreiben, sofern die Sprache das erlaubt (CMake vornehmlich), einfach weil sich die Logik so für mich besser "parsen" lässt.

    Das ist natuerlich kein Argument, dass rein von der Sprache selbst handelt. Aber als C++ Coder argumentiert man nie "ueber die Sprache eo ipso", weil ihr Einsatz nicht Selbstzweck ist, oder irgendein esoterisches Kunstwerk; sondern er erschafft im Idealfall ein Program, dass andere leicht erweitern und warten koennen.

    Und das setzt voraus, dass die Wahl der Stilistik nicht allzu exotisch ist. Im Umkehrschluss: Je mimetischer der Stil, desto hilfreicher ist er den Lesern. Wo es also keinen triftigen Grund gibt davon abzuweichen, sollte man sich daran halten.

    S.o. Wahrnehmungs- und Gewöhnungssache. Ich stimme dir schon zu, dass ein unorthodoxer Stil erst einmal schwerer zu lesen ist. Für mich ist aber die Frage, ob das auch noch dann der Fall ist, wenn man sich daran gewöhnt hat. Wenn der neue Stil dann immer noch schwerer zu lesen ist, dann hast du recht und der taugt nix. Es kann allerdings auch umgekehrt sein und dann hätte einen die eigene Voreingenomenheit daran gehindert, da herauszufinden. Um mal besonders dick aufzutragen: Das könnte viellecht wie ein auf rechts trainierten Linkshänders sein, der nie herausfindet, wie viel leichter das Schreiben mit der linken Hand ginge 😉

    • Du erwaehnst, dass die Funktionsnamen damit auf die gleiche Spalte ausgerichtet werden. Das ist aber nur hilfreich, wenn mehrere Deklarationen unmittelbar hintereinander stehen. main() wird immer definiert, hier zieht das also nicht. I.A. ist es bzgl. Lesbarkeit egal ob ein Name auf der 5ten oder 12ten Spalte steht, Hauptsache es ist nicht die 40ste.

    Ich weiss nicht wie viel Code du schon gesehen hat, wo das konsequent durchgezogen wurde, aber für mich zieht sich die visuell leichte Auffindbarkeit der Funktionsnamen auch durch die Definitionen. Man gewöhnt ich daran, dass die Funktionsnamen immer in der 6. Spalte beginnen - besonders wenn die Funktionen meist ohnehin nur wenige Zeilen lang sind. Kein "Augenparsen" notwendig. Zumindest bei mir springt der Blick immer direkt auf den Namen. Ich kann das also so nicht bestätigen. Ansonsten profitieren m.E. natürlich besonders Klassendelarationen von dieser Schreibweise - deren klarere visuelle Struktur ist mir die extra auto->-Tipparbeit wert.

    Ich möchte auch nochmal besonders unterstreichen, dass ich die Funktionsnamen eben auch für die wichtigere Information halte, als den Return Type. Es macht also durchaus Sinn, wenn dieser in Leserichtung zuerst erscheint.

    Wie du sehen kannst, reagiere ich nicht gut auf solche Null-Argumente.

    Ich hatte zuerst gelesen "ich reagierre nicht auf solche Null-Argumente", und wollte schon widersprechen, als ich das "gut" entdeckt habe 😃

    Ich kann akzeptieren, dass du die Schreibweise als "nicht besser" empfindest. Schlechten Stil (wie deine Antwort stark impliziert hat) lasse ich mir aber nur ungern bei einer Sache vorwerfen, über die ich mir lange Zeit Gedanken gemacht habe. Erst recht nicht, wenn es so schwach argumentiert und mit diesen Spitzen daherkommt. Aber das hat du ja in deiner ausführlichen Antwort nachgeholt, warum nicht gleich so? 😉



  • @Th69 sagte in Trailing Return Types Everywhere:

    @Finnegan: Bei dir sieht es aber nur so harmonisch aus, weil die Funktionsnamen und Parameter (Typen + Namen) gleich lang sind. In den meisten Fällen ist der Code dann m.E. noch schlechter (unruhiger) zu lesen.

    Dass sehe ich nicht so, und dass alle Funktionen die selben Parameter haben ist eher der Faulheit bei diesem Beispiel geschuldet als dem Versuch, das noch "harmonischer" aussehen zu lassen. Mein primäres Argument ist die Position des Funktionsnamens, nicht was dahinter kommt. Dieser ist meines erachtens die wichtigste Information und steht so immer in der selben Spalte. Das ist auch dann ein Vorteil, wenn es sich eben nicht nur um Deklarationen handelt, sondern auch bei längeren Definitionen. Irgendwann gewöhnt man sich daran, dass der Funktionsname immer in der 6 Spalte beginnt. Bei Code, wo das nicht so ist, muss muss ich immer spürbar für ein paar Sekundenbruchteile mit den Augen parsen - besonders wenn es sich um verschachtelte Template-Typen mit viel "Text-Rauschen" handelt. Nicht zuletzt deshalb verteidige ich das hier auch so vehement.

    Es gibt auch noch die Möglichkeit den Rückgabetyp in einer extra Zeile voran zu stellen:

    std::vector<int>
    f1(int a, int b);
    
    int
    f2(int a, int b);
    
    // alternativ mit Einrückung (zumindestens bei Deklarationen)
    std::pair<std::string, int>
      f3(int a, int b);
    
    void
      f4();
    

    Ja, das ist auch eine Variante. In der Tat verwende ich das auch in meinem Code-Stil, allerdings nur static, export, constexpr oder compiler-spezifische Attribute (__attribute__, etc.).

    Einer der Gründe für den konsequenten Trailig Return Type ist nämlich tatsächlich auch die einheitliche Verwendung einer Schreibweise, und da diese eben bereits diese vorteilhafte visuelle Struktur gibt, mache ich das bei Rückgabetypen eben nicht mehr so wie in deinem Beispiel. Aber in der Tat, gäbe es keine Trailig Return Types würde ich es wahrcheinlich heute auch noch so schreiben.


    Mit eurer Diskussion habt ihr aber wohl @Hawaiihemd verschreckt (ihr solltet euch mal in die Situation eines C++ Anfängers zurückversetzen, der gerade die ersten Kapitel eines C++ Buchs durchgelesen hat).

    Das war nicht meine Absicht, zumal ich mir diesbezüglich schon wegen dem Range-Concept-Beispiel Sorgen gemacht habe. Es gibt aber manchmal Beiträge, die ich nicht einfach unbeantwortet lassen kann*. Gut dass das hier ausgelagert wurde.

    * mit einem simplen "oh, das ist aber barock!" als Kommentar wär das nicht passiert 😉


  • Mod

    @Finnegan sagte in Trailing Return Types Everywhere:

    @Columbo sagte in Trailing Return Types Everywhere:

    Mein vollkommen objektives Argument war,

    Bei "vollkommen" möchte ich widersprechen. Gerade bei der Sache mit dem Rust-Seitenhieb mit dem fn-Makro und Formulierungen wie "unbedacht neue Features in den Code klatschen" schimmert schon eine gewisse Abneigug gegen diese Schreibweise durch.

    "Mein Argument" ist Singular. Der Witz mit den fn war fast schon kein Witz, aber der Emoji sollte klar stellen, dass es nicht als ernster Beitrag zur Diskussion (oder gar Ergaenzung meines Arguments) intendiert war.

    Ich vermute, das liegt daran, dass das für dich ein eher "exotisches" Sprachfeature zu sein scheint:

    Nein, denn "exotisches Sprachfeature" und "exotischer Stil" sind nicht dasselbe. Fuer mich ist dieses Feature nicht exotisch, wie ich durch meine Auflistung der adaequaten use cases auch gezeigt habe (wobei da sogar noch einer fehlt, kommt wer drauf?). Ich stoere mich daran, dass es zweckentfremdet wird.

    Meine Perspektive drauf ist eher neutral: Ich sehe hier lediglich zwei mindestens gleichwertige alternative Schreibweisen, von denen eine sogar noch ein wenig mächtiger ist (z.B. bei von template-parametern abhängigen Rückgabetypen).

    Die Maechtigkeit spielt dort eine Rolle, wo sie noetig ist. Nicht bei main(). Ich habe es konkret in diesem Rahmen kritisiert.

    Abgesehen davon begreife ich nicht, warum Du meinst, dass ein von Template-Parametern abhaengiger Rueckgabetyp i.A. mit trailing return type geschrieben werden muss?

    Für mich ist diese Diskussion daher eher wie East Const vs West Const oder int* x vs int *x, also eigentlich müßig. Jeder Entwickler und jedes Team hat seine Präferenzen und auch ein angehender Entwickler muss ohnehin lernen, mit beiden Varianten umzugehen und je nach Projekt diese auch zu schreiben - und sei es nur weil der Trailing return Type eben manchmal notwendig ist. Der einzige Grund, weshalb es als nicht "normal" empfunden wird ist, dass man es eben eher selten sieht. Würde das öfter verwendet, gäbe es diese Disussion wahrscheinlich nicht in dieser Form - eher auf West/East-Const-Niveau. Und das, obwohl sich an den objektiven Argumenten immer noch die selben wären.

    Mein Argument war doch gerade, dass es selten ist, und keinen unmittelbaren Vorteil bringt. Waere es verbreitet dann haette ich es auch nicht kritisiert. Es gibt (IMO) ein objektives Argument gegen seltene Schreibweisen von Dingen, weil sie Zeit rauben, wenn Leser ihnen begegnen. Es ist, wie erwaehnt, dem Lesefluss zutraeglich, mimetischen Stil zu hegen.

    Diese Anpassungsfähigkeit wird immer erforderlich sein. Im besonderen gilt das für C++, das wohl von allen Sprachen am weitesten von einem sprachübergreifend etablierten Code-Stil entfernt ist. Auch ein Anfänger sollte das lernen - aber ich stimme zu, dass das besser erst dann passieren sollte, wenn die Grundlagen sitzen. Und auch gerade bei Open Source ist die Wahrscheinlichkeit gross, dass man mit sehr vielen unterchiedlichen Stilen zurecht kommen muss - sei es durch nicht selten laxere Stilvorgaben oder eben durch viele kleine Beiträge zu sehr unterschiedlichen Projekten.

    Ich mag da aber auch eine etwa spezielle Sichtweise haben, da ich regelmässig mit sehr unterschiedlichem Code aus verscheidenen Projekten konftrontiert bin. Wenn ich seit vielen Jahren immer nur den Code des selbens Projekt in einem einheitlichen Stil gesehen hätte, würden mir Abweichungen wahrscheinlich auch erstmal unangenehm ins Auge fallen.

    Kennst Du ein einziges Open Source Projekt, dass auto main() schreibt?
    Ich stimme zu, dass Stilvorgaben variieren. In meiner alten Firma war West const vorgegeben; als ich rational dagegen argumentieren wollte, fuehrte das nirgendswo hin. Ich habe meine Meinung mittlerweile auch geaendert: east const ist so selten nuetzlich, und west const ist leichter zu erfassen, weil das vorausgehende const direkt erkennbar ist.

    Wenn wir von Einheitlichkeit sprechen, dann wird Einheitlichkeit ueber viele Projekte hin mEn. mehr wiegen, als Einheitlichkeit innerhalb eines Projekts. Nur weil Du irgendwo trailing return types brauchst, muss man sie nicht ueberall einsetzen.

    Globale Einheitlichkeit in C++ halte ich für eine Illusion und beschränke mich darauf mir für eigene Projekte einen Stil zu entwickeln, den ich als sinnvoll erachte und mich ansonsten an das Team anzupassen, in dem ich mitarbeite.

    Darf ich fragen: Arbeitest Du in einem Unternehmen, oder bist Du selbststaendig/contractor?

    Das heisst aber nicht, dass ich alles was in diesen Style Guides steht gut finden muss. In denen steht nämlich nicht selten auch eine Menge fragwürdiges Zeug. Gut und richtig, wenn man sich in einem Unternehmen oder für ein Projekt auf einen einheitlichen Stil geeinigt hat, das ist aber kein Grund auch Dinge, bei denen man gute Argumente dagegen hat in Zement zu gießen und überall anzuwenden - nur weil andere das auch tun und man das "schon immer so gemacht hat". Diese Mentaltität ist meiner Meinung mit einer der Gründe dafür, weshalb im C++-Umfeld "C mit Klassen" oder C++98-Stil immer noch so prävalent sind.

    I agree! Man muss modernes C++ auch ein Stueck weit selber verteidigen (bzw. dafuer kaempfen), denn da draussen sind viele renitente Leute.

    • man damit auch andere Leser allgemein irritiert, so wie z.B. mich, und wahrscheinlich die allermeisten Programmierer

    Aus der Perspektive, die Trailing Return Types eben als "exotisches" Feature sieht, ist die Irritation natürlich nachvollziehbar. Du solltest aber auch versuchen meine Sichtweise zu verstehen, dass es für mich eben ist, wie wo das const oder wo der Pointer-Stern steht. Mit dieser Wahrnehmung geht es dann wirklich nur noch darum, was man als besser lesbar empfindet.

    Geht es fuer Dich primaer darum, was Du als lesbar empfindest, oder die Leser deines Codes? Wird dein Code ueberhaupt gelesen? (deshalb auch die obige Frage nach der Natur deiner Beschaeftigung)

    Es ist analog zur Debatte ob man && oder and schreiben soll: Ich wuerde subjektiv argumentieren, and/or liest sich irgendwie huebscher, und hat auch nicht wirklich irgendwelche Nachteile, aber trotzdem waere es suboptimal es irgendwo einzusetzen, weil es einfach nicht der modus vivendi der Industrie ist, und folglich die Lesbarkeit darunter deutlich leidet.

    Ich weiss das das nur ein Beispiel für "gleichwertige Schreibweisen" ist (sind and/or nicht schon deprecated oder trügt mich meine Erinnerung?) dennoch ein paar Argumente:

    Nein, and/or sind und bleiben gueltig.

    &&/ || sind gleich lang und führen nicht dazu, dass eine Zeile länger oder kürzer wird, wenn man das eine durch das andere ersetzt.

    Warum sollte man das jemals muessen? Im Uebrigen schreibe ich die Operatoren bei laengeren Zeilen an das Zeilenende:

    if ((A and
         B) or
        C)
    

    Den größten Vorzeil sehe ich allerdings in der Verwendung von Symbolen vs Buchstaben, weshalb diese Operatoren für mich deutlicher deutlicher ins Auge stechen. and und or könnten auf en ersten Blick auch Identifier sein. Daher finde ich einen Ausdruck, der &&/|| verwendet leichter zu lesen. In Sprachen mit and/or tendiere ich daher sogar dazu, diese Operatoren groß zu schreiben, sofern die Sprache das erlaubt (CMake vornehmlich), einfach weil sich die Logik so für mich besser "parsen" lässt.

    Meine IDE highlighted and/or als keywords. Muss man einstellen, aber ich stimme zu, dass das nicht ueberall konfiguriert ist und ggf. bei Lesern ohne IDE Einstellung dann zu Verwirrung fuehren kann. Das ist tatsaechlich ein gutes Argument.

    Das ist natuerlich kein Argument, dass rein von der Sprache selbst handelt. Aber als C++ Coder argumentiert man nie "ueber die Sprache eo ipso", weil ihr Einsatz nicht Selbstzweck ist, oder irgendein esoterisches Kunstwerk; sondern er erschafft im Idealfall ein Program, dass andere leicht erweitern und warten koennen.

    Und das setzt voraus, dass die Wahl der Stilistik nicht allzu exotisch ist. Im Umkehrschluss: Je mimetischer der Stil, desto hilfreicher ist er den Lesern. Wo es also keinen triftigen Grund gibt davon abzuweichen, sollte man sich daran halten.

    S.o. Wahrnehmungs- und Gewöhnungssache. Ich stimme dir schon zu, dass ein unorthodoxer Stil erst einmal schwerer zu lesen ist. Für mich ist aber die Frage, ob das auch noch dann der Fall ist, wenn man sich daran gewöhnt hat. Wenn der neue Stil dann immer noch schwerer zu lesen ist, dann hast du recht und der taugt nix. Es kann allerdings auch umgekehrt sein und dann hätte einen die eigene Voreingenomenheit daran gehindert, da herauszufinden. Um mal besonders dick aufzutragen: Das könnte viellecht wie ein auf rechts trainierten Linkshänders sein, der nie herausfindet, wie viel leichter das Schreiben mit der linken Hand ginge 😉

    Also willst Du eigenhaendig die Revolution zu den trailing return types anzetteln? 😃

    • Du erwaehnst, dass die Funktionsnamen damit auf die gleiche Spalte ausgerichtet werden. Das ist aber nur hilfreich, wenn mehrere Deklarationen unmittelbar hintereinander stehen. main() wird immer definiert, hier zieht das also nicht. I.A. ist es bzgl. Lesbarkeit egal ob ein Name auf der 5ten oder 12ten Spalte steht, Hauptsache es ist nicht die 40ste.

    Ich weiss nicht wie viel Code du schon gesehen hat, wo das konsequent durchgezogen wurde, aber für mich zieht sich die visuell leichte Auffindbarkeit der Funktionsnamen auch durch die Definitionen. Man gewöhnt ich daran, dass die Funktionsnamen immer in der 6. Spalte beginnen - besonders wenn die Funktionen meist ohnehin nur wenige Zeilen lang sind. Kein "Augenparsen" notwendig. Zumindest bei mir springt der Blick immer direkt auf den Namen. Ich kann das also so nicht bestätigen. Ansonsten profitieren m.E. natürlich besonders Klassendelarationen von dieser Schreibweise - deren klarere visuelle Struktur ist mir die extra auto->-Tipparbeit wert.

    Ich möchte auch nochmal besonders unterstreichen, dass ich die Funktionsnamen eben auch für die wichtigere Information halte, als den Return Type. Es macht also durchaus Sinn, wenn dieser in Leserichtung zuerst erscheint.

    Ich stimme zu. Allerdings haben wir einerseits das Problem, dass bei lexikalisch externer Definition von Memberfunktionen der Name hinter dem Klassennamen steht, und deshalb sowieso schwerer zu finden ist. Andererseits gilt das auch IMO (also subjektiv fuer mich) nur bei Rueckgabetypen von mehr als X Zeichen (wo X vllt. 12 oder so ist).

    Ich kann akzeptieren, dass du die Schreibweise als "nicht besser" empfindest. Schlechten Stil (wie deine Antwort stark impliziert hat) lasse ich mir aber nur ungern bei einer Sache vorwerfen, über die ich mir lange Zeit Gedanken gemacht habe. Erst recht nicht, wenn es so schwach argumentiert und mit diesen Spitzen daherkommt. Aber das hat du ja in deiner ausführlichen Antwort nachgeholt, warum nicht gleich so? 😉

    Ich hatte nicht damit gerechnet, dass Du tatsaechlich fest dahinter stehst. Dann kann man natuerlich eine sinnvolle Diskussion fuehren, und das haben wir auch, ich finde die erwaehnten Punkte erkenntnisreich.



  • Ich seh das ziemlich pragmatisch. Trailing return type hat für mich keinen Vorteil der wichtig genug wäre nen Mischmasch anzufangen. Und da die allermeisten Projekte es halt nicht bzw. kaum verwenden, limitiert man es idealerweise auf die paar wenigen Fälle wo es wirklich Sinn macht.


Anmelden zum Antworten