C++11, C++14, C++17 - Modernes C++ bei euch schon angekommen?



  • Alles Neue ist C++14 und wird C++17, sobald VC++ mit auto -Templateargumenten klarkommt. (Die meisten noch ausstehenden C++17-Features wie fold expressions und pack expansion in using declaration vereinfachen nur den backstage-Code in meinen Bibliotheken, aber nicht den Anwendercode.)

    Es mag schon sein, daß man als Anwender ganz gut mit C++98 plus auto und range-based for loop auskommt. Aber man sollte bedenken, wie die Bibliotheken aussähen (bzw. aussahen) ohne variadic templates, static_assert() , type traits, initializer lists, Lambda-Funktionen oder constexpr , und wie viel Kontakt man also unvermeidlich mit C++1x-Features hat, ohne sie explizit zu gebrauchen.



  • Die Bibliotheken mögen gerne die neuen komplexen Sprachfeatures nutzen. Und ich als Benutzer profitiere davon. Aber nicht jeder ist Bibliotheks-Entwickler. Ich will mich damit auch gar nicht auseinander setzen, ich will meine Anwendungen fertig bekommen. Und dann ist mir der Coolness-Faktor egal.

    Die Anwendung muss fehlerfrei und schnell laufen. Und ich muss es schnell fertig bekommen.

    Dafür reicht mir hauptsächlich das C++98 plus die neue Standard-Lib.

    Ich würde es deshalb eher begrüssen, wenn endlich die Header-Dateien verschwinden würden, damit man nicht andauernd die DRY-Regel bricht und sich auf die eigentliche Problemlösung konzentrieren kann.
    Das würde C++ endlich in das aktuelle Jahrtausend katapultieren.



  • Artchi schrieb:

    Ich würde es deshalb eher begrüssen, wenn endlich die Header-Dateien verschwinden würden, damit man nicht andauernd die DRY-Regel bricht und sich auf die eigentliche Problemlösung konzentrieren kann.

    wozu soll das gut sein, dass die Header-Dateien verschwinden?

    Der Compiler muss beim Aufruf von externen Funktionen deren Signatur kennen, sonst kann er keine Typprüfung durchführen und keinen Typsicheren Code für den Aufruf der externen Funktion produzieren.

    Wie soll das ohne ein Header-File mit den entsprechenden Prototypen gehen, wenn die externe Library nicht open-Source ist (im Fall open Source wäre es immerhin möglich, dass der Compiler den Quellcode der Library durchgeht und sich die Prototypen selber herstellt)?



  • Du wirst die header files alleine aus backwards-compability gruenden nicht weg bekommen...



  • zufallswert schrieb:

    (Artchi schreibt, warum er Headerdateien loswerden will)

    wozu soll das gut sein, dass die Header-Dateien verschwinden?

    🤡

    zufallswert schrieb:

    Der Compiler muss beim Aufruf von externen Funktionen deren Signatur kennen, sonst kann er keine Typprüfung durchführen und keinen Typsicheren Code für den Aufruf der externen Funktion produzieren.

    Wie soll das ohne ein Header-File mit den entsprechenden Prototypen gehen

    Vielleicht hast du das nicht mitbekommen, aber dieses Problem ist in praktisch jeder seit den 70ern entwickelten Sprache ohne Headerdateien gelöst worden. Spezifisch für C++ gibt es das "Modules-TS", das es vielleicht nach C++20 schafft.



  • dieses "Problem", wie du es nennst, ist kein Problem, sondern eine Lösung 💡



  • audacia|off schrieb:

    zufallswert schrieb:

    wozu soll das gut sein, dass die Header-Dateien verschwinden?

    🤡 Vielleicht hast du das nicht mitbekommen, aber dieses Problem ist in praktisch jeder seit den 70ern entwickelten Sprache ohne Headerdateien gelöst

    von den "praktisch jede"-Sprachen "seit den 70ern", die du hier wohl meinen könntest, hört man aber relativ wenig, verglichen mit C.

    Ein Indiz dafür, dass Header-Files und Funktions-Prototypen doch keine so dumme Idee sind? 🙂



  • zufallswert schrieb:

    von den "praktisch jede"-Sprachen "seit den 70ern", die du hier wohl meinen könntest, hört man aber relativ wenig, verglichen mit C.

    Klar, diese Sprachen sind total Praxisfern und unbekannt:

    D
    Rust
    Go
    Eiffel
    OCaml
    C#
    Java

    Irgendwie ist nur C und C++ noch mit Header-Files unterwegs. Der Rest der Programmierwelt schafft es komischerweise ohne auszukommen. Nur C und C++ haben die Lösung, die anderen haben nur Probleme.



  • Artchi schrieb:

    Klar, diese Sprachen sind total Praxisfern und unbekannt:

    D
    Rust
    Go
    Eiffel
    OCaml
    C#
    Java

    Naja von den ersten 5 auf der Liste hört man wirklich vergleichweise wenig. Was ja die Behauptung war, nicht dass die alle total praxisfern und unbekannt wäre.



  • zufallswert schrieb:

    Ein Indiz dafür, dass Header-Files und Funktions-Prototypen doch keine so dumme Idee sind? 🙂

    Nein. Ein Indiz dafür dass C und C++ insgesamt immer noch so relevant sind dass man sie immer noch verwendet, trotz dem sie diverse Schwächen haben. Wie z.B. die Sache mit den Header-Files.



  • Schon alleine die Include-Guards sind einfach nur lästig.

    Ich kann absolut nichts gutes an den Headern finden.

    Naja von den ersten 5 auf der Liste hört man wirklich vergleichweise wenig. Was ja die Behauptung war, nicht dass die alle total praxisfern und unbekannt wäre.

    Das ist ja nun wirklich kein Argument, ob etwas technisch umsetzbar ist? Denn es wurde ja angezweifelt, das es technisch sinnvoll ist. dann mögen zwar die Beweise nicht so verbreitet sein, aber sie belegen die technische Machbarkeit.



  • @Artchi
    Er. Klar ist es technisch (recht einfach) machbar, bei Sprachen die kein Legacy-Gedöns mitzuschleppen haben.

    Für C++ ist es auch machbar, nur halt nicht so einfach wie wenn man von der grünen grünen Wiese wegstartet. Und daher noch nicht fertig. Kommt aber.

    Egal.
    Dass Headers nicht so toll sind, darüber sind wir uns ja einig 🙂



  • Ach ja, Swift von Apple habe ich natürlich vergessen. Das wird doch sicherlich unter OSX und iOS bei neuen Projekten vermehrt eingesetzt?

    Swift wollte ich mir auch noch mal anschauen...



  • hustbaer schrieb:

    zufallswert schrieb:

    Ein Indiz dafür, dass Header-Files und Funktions-Prototypen doch keine so dumme Idee sind? 🙂

    Nein. Ein Indiz dafür dass C und C++ insgesamt immer noch so relevant sind dass man sie immer noch verwendet, trotz dem sie diverse Schwächen haben. Wie z.B. die Sache mit den Header-Files.

    Doch! Funktionsprototypen und Header-Files sind eine im Grunde genial einfache, flexible und zweckmäßige Lösung für das Problem der Typprüfung zur Compile-Zeit bei Aufrufen externer Funktionen. Hätte gar nicht gedacht, dass es über diesen Punkt so viel zu diskutieren gibt.

    Wen es stört - schreibt doch ein Tool, das die Prototypen aus den Implementationsdateien automatisch extrahiert. Mich stört das ctrl-c ctrl-v zum Kopieren der Signatur ins Header-File nicht.



  • Copy & Paste 😃 👍 Das ist das erste was ich unseren Fachinformatik-Azubis austreibe! Copy & Paste machen wirklich nur Anfänger gerne ohne sich zu schämen.

    Und wenn du mal eine Signatur änderst? Dann musst du wieder an einer anderen Stelle anfassen, was du kopiert hast. Also wie man das ohne rot zu werden propagieren kann, ist mir unverständlich.

    DON'T REPEAT YOURSELF! würde ich dir raten, als großen Banner in dein Büro zu hängen.



  • zufallswert schrieb:

    Doch! Funktionsprototypen und Header-Files sind eine im Grunde genial einfache, flexible und zweckmäßige Lösung für das Problem der Typprüfung zur Compile-Zeit bei Aufrufen externer Funktionen. Hätte gar nicht gedacht, dass es über diesen Punkt so viel zu diskutieren gibt.

    Entweder du trollst, oder du bist ganz schön renitent.

    Welchen Vorteil soll es denn haben, statt eines Modulsystems wie in Java oder C# diese Headerdateien zu verwenden?



  • @zufallswert
    Nehmen wir als Beispiel eine Klasse Foo die private Member mit 5 verschiedenen eigenen Typen hat. Diese 5 Typen haben sagen wir mal wieder Member mit in Summe 15 verschiedenen eigenen Typen. Und diese wiederrum brauchen sagen wir in Summe 40 verschiedene #includes, z.B. aus der STL, Boost etc. Das ist nicht wirklich unrealistisch.

    Wenn du
    #include "Foo.h"
    schreibst ziehst du damit also 21 eigene Headers + 40 fremde (Boost, STL, ...) Headers an. Wobei die fremden Headers natürlich auch wieder weitere fremde Headers anziehen. In Summe kommst du ganz schnell auf etliche hundert Headers. Mit etlichen zigtausend~hunderttausend Zeilen Code (Prototylen, Klassendefinitionen inklusive Inline implementierter Funktionen etc.).
    Dabei sind dann "ein paar" Templates. Je "moderner" desto mehr. Auch schnell mal ein paar hundert oder gar tausend in Summe. Wovon dann ein paar zig bis hundert wirklich instanziert werden.
    Bam, Oida!

    Und wenn wir davon ausgehen dass die Klasse Foo nichts inline implementiert hat, dann brauchen wir das ganze nur, damit man sizeof(Foo) ausrechnen kann und damit der Compiler "glücklich" ist (Information über Memberfunktionen sämtlicher Klassen ausser Foo würden ja z.B. gar nicht benötigt.)
    OK, eine Kleinigkeit hab' ich unterschlagen: die implizit definierten "special member functions" (copy-ctor und so).
    Aber auch da bräuchte man eigentlich nur jeweils die Info ob es sie gibt und was ihre genaue Signatur ist.

    Es müssen also zigtausend Zeilen Code geparsed werden, nur damit ein paar wenige Integers (sizeof) und Signaturen (special member functions) errechnet werden können + damit keine "language rules" verletzt werden (z.B. dass sämtliche Memberfunktionen direkt in der Klassendefinition angegeben werden müssen, auch wenn man sie in der Translation-Unit gar nicht braucht).

    Und jetzt sag mir dass das effizient ist. Ist es nicht.

    Ich hab' nicht grundsätzlich ein Problem damit dass es schöne Textfiles gibt wo man die API nachlesen kann. Aber ich hab' ein Problem damit wenn das zu unsäglich langsamen Compilevorgängen führt. 10+ Sekunden zum Parsen nur der #includes für ein einzelnes .cpp File sind echt keine Seltenheit.

    Und was mMn. auch nicht so toll ist, ist dass Code, damit er "geinlined" werden kann, im Header File stehen muss. (Klar, das muss er nicht mehr wenn man LTCG verwendet. Nur LTCG macht alles NOCH viel langsamer. Von daher...)



  • audacia schrieb:

    Welchen Vorteil soll es denn haben, statt eines Modulsystems wie in Java oder C# diese Headerdateien zu verwenden?

    Ich sehe es als Vorteil dass man, ohne irgendwelche Tools, die Headers aufmachen und sich die API angucken kann.

    Ich würde dies aber liebend gerne gegen schnellere Compilezeiten und die anderen Vorteile eintauschen 🙂

    Vorausgesetzt dass es Tools gibt, mit denen man die relevanten Informationen aus den Modules extrahieren kann. Aber da sich diese Tools automatisch einfinden werden wenn wir erstmal Modules haben, egal ob sie mit der Implementierung mitkommen oder nicht...



  • Was genau ist bei Modulen anders als bei Header Files?
    Im Prinzip sollte beides das gleiche sein.

    Bei Modulen muss ich doch auch jedes mal alle benötigten Module einbinden und dass können dann auch immer mehr und mehr werden bei großen Projekten.

    Bitte um Aufklärung. 😕



  • Und was spricht dagegen die Definition der Klassen in den Header Dateien durchzuführen statt in .h und .cpp aufzuteilen?


Anmelden zum Antworten