Ist goto xy wirklich so böse?



  • happystudent schrieb:

    Gerade beim Erstellen einer eigenen for Schleife wehrt sich die Aufgabe aber nicht "mit Händen und Füßen", sondern ist geradezu prädestiniert dafür, z.B. concurrency::parallel_for oder std::for_each .

    Naja sie wehrt sich zumindest ein bisschen, wenn du die Schleife vorzeitig abbrechen willst. Und std::for_each ist IMO auch ein ganz schlechtes Beispiel, weil in C++11 mMn. völlig redundant. parallel_for macht natürlich Sinn.

    happystudent schrieb:

    Und da ich i , wie in einer normalen inneren for-Schleife ändern können will, capture by reference.

    Wenn du hier schon facepalmst dann bitte mit Begründung, bin gespannt 🙂

    Die Möglichkeit i ändern zu können macht in deinem Beispiel überhaupt keinen Sinn. Schlimmer noch: wenn man so etwas wie dein "my_for" bastelt, dann will man normalerweise gar nicht dass der Funktor die Laufvariable ändern kann.

    Man *kann* das machen, wenn es denn wirklich Sinn macht, und natürlich *kann* es Sinn machen. Dadurch werden aber Dinge die eigentlich Implementierungdetails der Funktion sind zum Contract erhoben - auch wenn man sich darüber vielleicht nicht im klaren ist und es nicht dokumentiert.

    Nämlich z.B. wie die Laufbedingung ist. Also ob i != end oder i < end . Oder ob es evtl. sogar i >= begin && i < end ist - was nötig wäre wenn man dem Funktor auch erlauben möchte abzubrechen indem man i < begin setzt.
    Weiters geht ein recht angenehmer Nebeneffekt der Funktion verloren, nämlich dass man die Laufvariable eben gerade nicht ändern kann. Durch diesen komplizierteren Contract schränkst du nicht nur die Implementierung ein (schlechtere Performance wegen beidseitigem Range-Check) sondern machst das ganze auch aufwendiger zu verstehen. Also aufwendiger richtig anzuwenden, und ganz wichtig: auch aufwendiger zu lesen, da der Leser sich eben nicht mehr darauf verlassen kann dass die Schleife einfach immer genau 1x von vorn bis hinten durchpfeifft ohne was zu überspringen oder zu wiederholen.

    Und da aus dem Beispiel kein Grund erkennbar ist wieso man i ändern wollen würde (und das Beispiel i auch gar nicht ändert), ist dieses Detail in diesem Beispiel ein *facepalm*. Und nochmal mehr, weil es nichtmal gehen würde - der äussere Funktor nimmt i ja by-value.

    Alles in allem bleibt also der Eindruck dass hier entweder
    - grundsätzlich gerne by-reference gecaptured wird, was definitiv einen dicken *double-facepalm* verdient oder
    - ein Werkzeug wegen "könnte ja mal wer machen wollen" unnötig flexibel und damit auch unnötig komplex gemacht wurde - was zumindest einen einfachen *facepalm* verdient.

    happystudent schrieb:

    hustbaer schrieb:

    Ja, klar. Das schöne neue Werkzeug einfach mal für jede Aufgabe einsetzen, obwohl sich die Aufgabe mit Händen und Füssen dagegen wehrt, ist immer volle schlau.

    Weiß ja nicht wo du rausliest dass ich das für jede Aufgabe einsetze. 😕

    Ja, damit hast du Recht. Sorry!



  • hustbaer schrieb:

    Und std::for_each ist IMO auch ein ganz schlechtes Beispiel, weil in C++11 mMn. völlig redundant.

    Gab es eigentlich std::for_each und range based for schon immer zusammen? Weil wenn ja, macht das wirklich irgendwie wenig Sinn 😃

    hustbaer schrieb:

    Die Möglichkeit i ändern zu können macht in deinem Beispiel überhaupt keinen Sinn.

    Ok, jetzt verstehe ich was du meinst. Das stimmt natürlich, wollte für das Beispiel halt möglichst nahe an eine "richtige" for-Schleife rankommen - da kann man ja ohne weiteres auch i ändern. In der Realität würde ich das aber natürlich nicht capturen, wenn nicht notwendig.

    hustbaer schrieb:

    Ja, damit hast du Recht. Sorry!

    Kein Problem, aber es stimmt natürlich auch dass man das sparsam einsetzen sollte... Bei zwei Schleifen gehts noch, aber mehr würde ich dann wahrscheinlich auch nur ungern verwenden.



  • happystudent schrieb:

    hustbaer schrieb:

    Und std::for_each ist IMO auch ein ganz schlechtes Beispiel, weil in C++11 mMn. völlig redundant.

    Gab es eigentlich std::for_each und range based for schon immer zusammen? Weil wenn ja, macht das wirklich irgendwie wenig Sinn 😃

    Nein, std::for_each ist C++98 und range based for ist C++11. Aber range based for und Lambdas sind beide C++11. Es gibt also keinen Grund (zumindest keinen der mir einfällt) std::for_each mit Lambdas zu verwenden. Also ausser partiellem C++11 Support oder sowas.

    happystudent schrieb:

    hustbaer schrieb:

    Die Möglichkeit i ändern zu können macht in deinem Beispiel überhaupt keinen Sinn.

    Ok, jetzt verstehe ich was du meinst. Das stimmt natürlich, wollte für das Beispiel halt möglichst nahe an eine "richtige" for-Schleife rankommen - da kann man ja ohne weiteres auch i ändern.

    Ja, sowas, also dass man versucht etwas anderes möglichst 1:1 nachzubilden, kann einem schnell mal passieren. Ist aber oft gar nicht so gut, weil man damit eben oft etwas schafft was unnötig flexibel und damit unnötig kompliziert ist. In einem Beispiel natürlich nicht tragisch, aber wenn man so production Code entwirft finde ich das gar nicht so gut.


  • Mod

    hustbaer schrieb:

    Es gibt also keinen Grund (zumindest keinen der mir einfällt) std::for_each mit Lambdas zu verwenden.

    Iteratoren-Paar statt Range? Wir haben schließlich immer noch kein iterator_pair in der Standardbibliothek...



  • OK, das ist ein Grund der mir nicht eingefallen ist 🙂
    Wobei, wenn man es öfter braucht, ... die paar Zeilen die man für ne minimale iterator_pair Implementierung braucht... das könnte sich schon auszahlen.
    Und ich glaube ich würde das lieber machen als nur deswegen std::for_each zu verwenden. Bzw. ich würde boost::make_iterator_range() verwenden, aber angenommen ich hätte keine Boost...


Anmelden zum Antworten