Gast
#6536385
Hi ich arbeite zwar lange mit C, musste hier und da auch kleinere Projekte mit C++ angehen. sind diese ganzen Erweiterungen von c++11/14/17 weltbewegend und verbreitet? Auch im embedded Bereich? Klaus
|
Anzeige
|
c++ 11/14/17?
Gast
#6536385
Hi ich arbeite zwar lange mit C, musste hier und da auch kleinere Projekte mit C++ angehen. sind diese ganzen Erweiterungen von c++11/14/17 weltbewegend und verbreitet? Auch im embedded Bereich? Klaus
Gast
#6536394
Klaus schrieb: > sind diese ganzen Erweiterungen von c++11/14/17 weltbewegend und > verbreitet? Auch im embedded Bereich? Ja, ja, ja. Viele der Neuerungen sind für embedded sehr nützlich, wie z.B. Vorberechnung via constexpr. Es gibt kaum einen Grund sich auf den 18 Jahre alten Sprachstandard C++03 zu beschränken.
Gast
#6536401
Den Schritt zu c++11 würde ich schon weltbewegend bezeichnen. Aber bei so einer unspezifischen Frage kann man auch einfach ja/nein/vielleicht antworten ;) Klaus schrieb: > Hi > ich arbeite zwar lange mit C, musste hier und da auch kleinere Projekte > mit C++ angehen. > sind diese ganzen Erweiterungen von c++11/14/17 weltbewegend und > verbreitet? Definitiv. > Auch im embedded Bereich? Hmm, schwer zu sagen. Ich nutze sie dort. Kommt aber auch drauf an, was der verfügbare Compiler kann. Manche sind bei solchen Änderungen ja nicht gerade rasend schnell unterwegs, vor allem, wenn sie zertifiziert sein müssen. Klaus schrieb: > c++11/14/17 Inzwischen kannst du auch noch C++20 mit hinzunehmen. Einige der Neuerungen sind sehr praktisch und erleichtern das Programmieren, weswegen sich die Beschäftigung damit auf jeden Fall lohnt. Andere blähen IHMO die Sprache nur weiter auf und hätten genauso gut weggelassen werden können. Aber das ist ein allgemeines Problem bei Kommiteesprachen (nicht nur C++): Da will jeder Beteiligte auf Biegen und Brechen seine supertolle Idee in den Standard einbringen, und wenn der Vorschlag nicht völlig destruktiv ist, stimmen die anderen halt irgendwann zu, damit der Standardisierungsprozess nicht zu sehr ins Stocken gerät.
Gast
#6536599
Yalu X. schrieb: > Andere blähen IHMO die Sprache nur weiter auf und hätten genauso gut > weggelassen werden können. Was würdest du sagen bläht die Sprache nur auf?
Gast
#6536610
Rolf M. schrieb: > Manche sind bei solchen Änderungen ja > nicht gerade rasend schnell unterwegs, vor allem, wenn sie zertifiziert > sein müssen. Eben. Sicherheitsregel: "Never change a running system. Never run a changed system" !
Gast
#6536622
Hau wech den Scheiss schrieb: > Eben. Sicherheitsregel: "Never change a running system. Never run a > changed system" ! Nach dem Motto tut sich aber nie was, oder man müsste ständig komplett neue Sprachen erfinden um Neuerungen umzusetzen. Es gibt auf der ganzen Welt nicht genug Programmierer, um ständig alles in neue Sprachen neu zu implementieren, wenn man die neuen Features nutzen will. Yalu X. schrieb: > Andere blähen IHMO die Sprache nur weiter auf und hätten genauso gut > weggelassen werden können. Andere finden diese Features gut. Um nicht völlig von anderen Sprachen abgehängt zu werden, kann man dort etablierte Features übernehmen. C++ hat auch eine Daseinsberechtigung für neue Projekte, abseits der Pflege existierender Systeme, und hier möchte man vielleicht von neuen Features profitieren. Wer hat jetzt Recht?
Gast
#6536703
Programmierer schrieb: > Hau wech den Scheiss schrieb: >> Sicherheitsregel: "Never change a running system. Never run a >> changed system" ! > > Es gibt auf der ganzen > Welt nicht genug Programmierer, um ständig alles in neue Sprachen neu zu > implementieren, wenn man die neuen Features nutzen will. Eben. Warum irgendwelche modischen Neuerungen durchdrücken, wenn es weder die Manpower dafür gibt, noch irgendwelche Verbesserungen an der Sicherheit aka Kundenzufriedenheit zu erwarten sind.
Gast
#6536710
Hau wech den Scheiss schrieb: > Eben. Warum irgendwelche modischen Neuerungen durchdrücken, wenn es > weder die Manpower dafür gibt, noch irgendwelche Verbesserungen an der > Sicherheit aka Kundenzufriedenheit zu erwarten sind. Dann, gib mal wenigstens ein Beispiel aus dem c++20 Standard - das eine modische Neuerung und - zuwenig Manpower (was auch immer du damit meinen magst) hat und - keine Verbesserung an Sicherheit oder Kundenzufriedenheit erwarten lässt.
Gast
#6536719
Hau wech den Scheiss schrieb: > Eben. Warum irgendwelche modischen Neuerungen durchdrücken, wenn es > weder die Manpower dafür gibt, noch irgendwelche Verbesserungen an der > Sicherheit aka Kundenzufriedenheit zu erwarten sind. Worauf bezieht sich das jetzt? Neue Sprachfeatures wie z.B. Lambdas bedeuten einfachere und schnellere Entwicklung und Wartung, und dadurch geringere Entwicklungskosten und billigere Endprodukte, und billig macht Kunden zufrieden.
Gast
#6536739
Programmierer schrieb: > Hau wech den Scheiss schrieb: >> Eben. Warum irgendwelche modischen Neuerungen durchdrücken, wenn es >> weder die Manpower dafür gibt, noch irgendwelche Verbesserungen an der >> Sicherheit aka Kundenzufriedenheit zu erwarten sind. > > Worauf bezieht sich das jetzt? Neue Sprachfeatures wie z.B. Lambdas > bedeuten einfachere und schnellere Entwicklung und Wartung, und dadurch > geringere Entwicklungskosten und billigere Endprodukte, und billig macht > Kunden zufrieden. Es geht um Software-Qualifizierung also Sicherheitskritischer Bereich. Das kann schon Automotive sein, und da will der Kunde sicher und unbeschadet angekommen und zahlt dafür auch einen Aufschlag. Siehe Volvo. Die Software ist eben nicht nach der Entwicklung fertig, da schliesst sich mindestens noch die verifikatiopn an.Und da bleibt man lieber bei gut bewährter Software . Und die billigste Software ist immer noch die, die man schon hatund deren Schwachstellen man kennt.
Gast
#6536748
Hau wech den Scheiss schrieb: > Es geht um Software-Qualifizierung also Sicherheitskritischer Bereich. Seit wann? Hau wech den Scheiss schrieb: > Und da bleibt man lieber bei > gut bewährter Software . Warum? Neue C++-Versionen bieten bessere Möglichkeiten zur typsicheren (Meta-)Programmierung, damit kann man mehr Fehler direkt beim Kompilieren erkennen, wodurch sich die Fehlerwahrscheinlichkeit wieder reduziert. Hau wech den Scheiss schrieb: > da schliesst > sich mindestens noch die verifikatiopn an. Echte Verifikation wird in der Automobilindustrie nicht gemacht, da praktisch unmöglich. Leider sind die Toolchain-Anbieter im Embedded-Bereich seeeehr träge, was das Implementieren der "neuen" C++-Standards angeht. C++11 ist bei vielen schon das höchste der Gefühle. Aber ja: C++ hat viele Features, die auch im Embedded-Bereich sehr sinnvoll wären oder sind. In Automotive und Co (alles was mit FuSi zu tun hat), braucht man zertifizierte Komponenten, das schließt den Compiler, die Hardware, die Toolchain mit ein. Ein zertifizierter C++11 (wenn man überhaupt das Glück hat, C++ benutzen zu dürfen (!)) wird nicht mal eben durch einen C++17 (falls es den überhaupt "schon" gibt) ersetzt. Das ist zu teuer (denn man muss häufig dann mehrere Varianten parallel haben, um alte builds reproduzieren zu können) und dabei ist die Entwicklungszeit (Lambdas, constexpr etc) leider fast vollkommen egal - zumindest war es das in den letzten Firmen, die ich von innen gesehen habe. edit: Von Keil gibts beispielsweise gerade mal C++11: https://developer.arm.com/tools-and-software/embedded/arm-compiler/safety
Gast
#6536808
Programmierer schrieb: > Hau wech den Scheiss schrieb: >> Es geht um Software-Qualifizierung also Sicherheitskritischer Bereich. > > Seit wann? Seit der Aspekt der Software-Zertifizierung in den Thread geworfen wurde: Beitrag "Re: c++ 11/14/17?" Hau wech den Scheiss schrieb: >> Und da bleibt man lieber bei >> gut bewährter Software . >Warum? Naja, weil man davon ausgeht das sich Software die sich in der Vergangenheit als Fehlerarm gezeigt hat, auch in Zukunft das selbe Fehlerarme Verhalten zeigen wird. Software unterliegt keinem Verschleiß und muss daher nicht permanent erneuert werden. >Echte Verifikation wird in der Automobilindustrie nicht gemacht, da >praktisch unmöglich. Klar, und ich bin der Kaiser von China. Hau wech den Scheiss schrieb: >>Echte Verifikation wird in der Automobilindustrie nicht gemacht, da >>praktisch unmöglich. > > Klar, und ich bin der Kaiser von China. Ich denke, da hat er Recht. Echte aka formale Verifikation ist bei komplexen Zusammenhängen extremst aufwendig oder nahezu unmöglich. mh schrieb: > Dann, gib mal wenigstens ein Beispiel aus dem c++20 Standard ... > - zuwenig Manpower (was auch immer du damit meinen magst) hat Es geht dabei nicht um den Standard selbst, sondern um die Compiler-Entwickler, die das dann in ihren Produkten umsetzen müssen. Programmierer schrieb: > Neue C++-Versionen bieten bessere Möglichkeiten zur typsicheren > (Meta-)Programmierung, damit kann man mehr Fehler direkt beim > Kompilieren erkennen, wodurch sich die Fehlerwahrscheinlichkeit wieder > reduziert. Das basiert aber auf der Annahme, dass der Compiler selbst generell keine Fehler hat. Als Entwickler der Software hat man allerdings nur auf den Quellcode Einfluss, nicht aber auf den Compiler selbst. Hau wech den Scheiss schrieb: > Hau wech den Scheiss schrieb: >>> Und da bleibt man lieber bei >>> gut bewährter Software . > >>Warum? > > Naja, weil man davon ausgeht das sich Software die sich in der > Vergangenheit als Fehlerarm gezeigt hat, auch in Zukunft das selbe > Fehlerarme Verhalten zeigen wird. Software unterliegt keinem Verschleiß > und muss daher nicht permanent erneuert werden. Darüber hinaus kennt man bei länger verwendeter Software die bestehenden Fehler, und ein Wechsel auf eine neue Software würde die Fehler durch neue ersetzen, die man noch nicht kennt. Und bekannte Fehler sind immer besser als unbekannte. Deshalb wird auch in der Raumfahrt gerne "gut abgehangene" Hardware verwendet, also z.B. Prozessor-Typen, die es schon sehr lange gibt. Neben der geringen Komplexität sind dort auch mehr von den Fehlern bereits gefunden worden als bei neuerer Hardware. >>Echte Verifikation wird in der Automobilindustrie nicht gemacht, da >>praktisch unmöglich. > > Klar, und ich bin der Kaiser von China. Er meint mit "Verfikiation" vermutlich die Erbringung eines formalen Beweises für die Korrektheit.
Gast
#6536856
Jan K. schrieb: > Hau wech den Scheiss schrieb: >>>Echte Verifikation wird in der Automobilindustrie nicht gemacht, da >>>praktisch unmöglich. >> >> Klar, und ich bin der Kaiser von China. > > Ich denke, da hat er Recht. Echte aka formale Verifikation ist bei > komplexen Zusammenhängen extremst aufwendig oder nahezu unmöglich. Nur wenn man das Design und den Entwicklungsprozess nicht auf Verifikation hin auslegt. Schon mal was von Design for Testability gehört? Oder Test Automatisition Equipment? Fehlerinjektion? Also ich kenn da Automotive-Buden die haben mehrere Bladeracks und HIL-Aufbauten im Serverraum stehen, die nichts anderes machen als die Firmware Tagelang mit testpattern zu stressen. Hinzukommen die Tausenden Testfahrzeuge mit Protokollrecordern, die mehrere MannJahrzehnte an realen Szemarien aufzeichnen bevor der Automobilhersteller seine Freigabe erteilt. https://www.pcwelt.de/news/BMWs-autonome-Autos-1.500-TB-neue-Daten-pro-Tag-10564439.html Ntürlich wird in der Automobilindustire verifiziert -so gut und Vollständig es eben geht. Deshalb nimmt man ja auch unnötige Komplexität aus dem Produkt/Entwicklungsprozess. beispielsweise die, durch Zulassung neuer Code-Standards zwangsläufig entsteht. - "Never change a running system"
Gast
#6536863
Hau wech den Scheiss schrieb: > Nur wenn man das Design und den Entwicklungsprozess nicht auf > Verifikation hin auslegt. Schon mal was von Design for Testability > gehört? Oder Test Automatisition Equipment? Fehlerinjektion? Testen hat nichts mit Verifikation zu tun. Verifikation bedeutet, einen formalen mathematischen Beweis zu erbringen, dass die Software exakt der Spezifikation entspricht. Und das ist bei komplexer Software ein gewaltiger Aufwand. Um diesen zu vermeiden, testet man halt einfach möglichst viele (trotzdem nur ein verschwindend geringer Anteil) Fälle in der Hoffnung, dass die verbleibenden Fälle auch korrekt sind. C++20 Software kann man genau so testen wie C89-Software. Jan K. schrieb: > In Automotive und Co (alles was mit FuSi zu tun hat), braucht man > zertifizierte Komponenten, das schließt den Compiler, die Hardware, die > Toolchain mit ein. Nur braucht das der größte Teil der Software in einem Auto gar nicht. Und da zur Zeit jeder Kommentar über die deutsche Automobilindustrie in etwas lautet "können alles, ausser Software", würde ich auf die bisherigen Gepflogenheiten dort auch nicht allzuviel geben. Ich bin mir ziemlich sicher, daß weder Google, noch Apple oder Tesla sich mit Misratenen Normentwürfen herumschlagen. Die sitzen stattdessen in den C++-Normungsgremien, und gehen damit vorwärts. Oliver Oliver S. schrieb: > Ich bin mir ziemlich sicher, daß weder Google, noch Apple oder Tesla > sich mit Misratenen Normentwürfen herumschlagen. Die sitzen stattdessen > in den C++-Normungsgremien, und gehen damit vorwärts. Das stimmt vermutlich. Und glaub mir, ich bin über den langsamen Fortschritt auch angenervt, bekomme es tagtäglich auf der Arbeit mit. Möchte man aber Hardware/Module in einem Auto oder in der Industrie unterbringen, muss häufig nach den erwarteten Normen entwickelt werden. Macht man das nicht, bekommt man das Projekt nicht - ganz einfach. Und ISO26262 und co kommen gerade erst richtig und schwappen von purem Automotive in Richtung Transportation, Industrie, Baumaschinen etc. @Hau wech den Scheiss (Gast), du kennst leider den Begriff formale Verifikation nicht. Das hat nichts mit Testen zu tun. Natürlich wird viel getestet und wer seine Software samt Drumherum nicht testbar gestaltet, hat irgendwann grundsätzlich die A-Karte. Klaus schrieb: > sind diese ganzen Erweiterungen von c++11/14/17 weltbewegend ja > und > verbreitet? In diesem Forum stoßen sie regelmäßig auf Kritik ;-) Das scheint ein gutes Zeichen zu sein. > Auch im embedded Bereich? Eigentlich gerade da. Meine persönliche Hitliste im µC-Bereich (inkl. c++20) sind: 1) concepts: der Schlüssel zu compiletime-polymorphie und TMP 2) constexpr everywhere 3) lambda-expr. Verbesserungen (e.g. explicit template-lambda parameter) 4) stdlib: tuple<>, variant<>, bit_cast<>, etc. zusammen mit 2) 5) template-alias (using) und viele Kleinigkeiten vereinfachen die TMP mh schrieb: > Yalu X. schrieb: >> Andere blähen IHMO die Sprache nur weiter auf und hätten genauso gut >> weggelassen werden können. > > Was würdest du sagen bläht die Sprache nur auf? Zwei Beispiele, die mich besonders stören: 1. Die Uniform Initialization: Zu den bereits bestehenden mehreren Möglichkeiten der Initialisierug kommt nun noch eine weitere hinzu https://xkcd.com/927/ beschreibt die Situation ganz treffend, wenn man dort "standards" durch "initialization methods" ersetzt. Nicht ganz so schlimm fände ich die Uniform Initialization, wenn sie wenigstens die klassischen Initialisierungsmethoden komplett ersetzen könnte, aber das tut sie nicht. Dazu kommt noch, dass nun einige meinen, deren Verwendung auf die Spitze treiben zu müssen, so dass dann Stilblüten wie diese entstehen:
Das ist zwar legaler Code, aber was soll der Unfug? Anfangs habe ich die Uniform Initialization selber verwendet, u.a. um in meinem Code zu dokumentieren, dass ich mit der Zeit gehe und nicht an alten Zöpfen hänge ;-) Mittlerweile ist mir das egal, weswegen ich wieder zu den klassischen Initialisierungsmethoden zurückgekehrt bin. Mich spricht auch deren Syntax mehr an. 2. Typsynonyme mit using als Alternative zu typedef: Ich frage mich, was an der typedef-Syntax schlecht ist. Den einzigen Mangel sehe ich darin, dass typedef nicht getemplatet werden kann, ein Problem, das seit der Einführung der Templates in C++ (also schon lange vor C++11) diskutiert wird, aber nie behoben wurde. Statt einfach auch typedef-Templates zu erlauben, wurde die völlig neue using-Syntax eingeführt. Wozu? Habe ich irgendwelche schwerwiegende Gründe übersehen, warum das für typedef nicht möglich ist? Es gibt noch ein paar weitere IHMO unsinnige neue Features, die ich aber aus meinem Gesichtsfeld entschwunden sind, da sie auch von anderen kaum genutzt werden. Sie machen damit lediglich das Standarddokument und die Lehrbücher fett, stören aber wenigstens bei der täglichen Arbeit nicht. Bitte nicht missverstehen: Meine Kritik bedeutet keineswegs, dass ich zurück zu C++03 möchte, ganz im Gegenteil. C++11 und Nachfolger bringen insgesamt mehr positive als negative Erweiterungen mit. Die für mich wichtigsten positiven Punkte sind: 1. Range based Loops: Endlich kann man über die Elemente eines Containers ohne dieses lästige begin() und end() iterieren. 2. Lambda-Ausdrücke: C++ war eine der letzten Sprachen, die das noch nicht hatte, deswegen wurde es höchste Zeit, das nachzuliefern. 3. Neue Datentypen in Standardbibliothek Tuple, Optional, verschiedene Sorten von Smart Pointers usw. 4: π Ich hätte nicht geglaubt, dass das bisher GCC-spezifische M_PI noch irgendwann in den Standard aufgenommen werden wird. Seit letzten Dezember (C++20) ist es aber tatsächlich so weit: Es gibt jetzt u.a. std::numbers::pi in <numbers>. Ich frage mich nur, warum das fast ein halbes Jahrhundert gedauert hat. 5. Compilezeitberechnungen mit constexpr: Wenn ich sehe, wie man solche Dinge früher mit Template-Hacks hingedoktert hat (einige haben daraus eine regelrechte Wissenschaft gemacht), ist diese Erweiterung ein wirklicher Segen. 6. Contraints und Concepts: Endlich wird das leidige Problem mit dem Duck-Typing in Templates und den damit verbundenen schwer interpretierbaren Fehlermeldungen etwas entschärft. Diese Lösung ist zwar nicht besonders schön und bedarf zusätzlicher Zuarbeit vonseiten des Template-Entwicklers, aber mehr war unter Beibehaltung der Abwärtskompatibilität wohl nicht möglich. 7. Stark typisierte Enums Ein weitere Schritt zu mehr Fehlererkennung durch den Compiler. 8. Type Inference: Implementiert wurde zwar nur eine schwache Form davon, aber auch diese ist oft sehr hilfreich, bspw. bei der Deklaration eines Iterators zu einem gegebenen Container-Objekt. 9. Korrekte Unterscheidung zwischen doppelten Temnplate-Klammern und dem >>-Operator Früher musste bspw. bei std::vector<std::vector<int>> zwischen den beiden ">" ein Leerzeichen eingefügt werden. Das aus meiner Sicht größte Problem an C++ ist die Komplexität. Es gibt alles und dann noch die kleine Schwester davon. Im Ergebnis übersteigt die Komplexität der Sprache die Hirne der Entwickler, die dann nur einen kleinen Teil der Möglichkeiten überhaupt nutzen. Ohne einen übergeordneten Standard nutzt dann jeder noch einen anderen Teil, was die Sprache für Menschen schlecht lesbar machen kann. Kompatiblität ist schön und gut, aber im Drei-Jahres-Takt ausschließlich neue Dinge hinzufügen macht das nicht gerade besser. Das "es gibt mehr als eine gute Lösung" ist es, was Perl so nervig macht und C++ geht aus meiner Sicht den gleichen Weg. S. R. schrieb: > > Kompatiblität ist schön und gut, aber im Drei-Jahres-Takt ausschließlich > neue Dinge hinzufügen macht das nicht gerade besser. > > Das "es gibt mehr als eine gute Lösung" ist es, was Perl so nervig macht > und C++ geht aus meiner Sicht den gleichen Weg. Es gibt aus gutem Grund mehrere Lösungen. Denn wenn wegen neuer Ideen die alten Projekte nicht mehr übersetzbar sind, dann wird das wie bei Python 2 vs 3, wo auch heute noch beides parallel installiert sein muß. Wenn nun etwas, was bisher umständlich war, durch ein neues, eleganteres Verfahren ersetzt werden kann, dann sollte da ein "endlich" zu hören sein. Falls es es keine übergeordneten Gründe gibt, das komplizierte zu behalten (Zertifizierung). "Immer schon so gemacht" haben wir eben "auf den Bäumen sitzen". Ausnahmen würde ich bei so Dingen machen wie "ich habe 'volatile' nicht verstanden und plädiere dafür es abzuschaffen". Wenn sowas von Firmen kommt, die eigentlich lieber ihre homebrew Sprachen verwenden, da kann man über die wirklichen Gründe mutmaßen. Da ist Apple nicht anders als MS. Carl D. schrieb: > Es gibt aus gutem Grund mehrere Lösungen. Das ist mir schon klar und ich kann auch das C++-Konsortium verstehen. Ändert aber nichts daran, dass der enorme Sprachumfang allein schon dafür sorgt, dass niemand die Sprache mehr vollständig überblicken kann. Fällt z.B. immer dann auf, wenn bei den Vorträgen mal in die Runde gefragt wird, welchen Datentyp (oder welche Fehlermeldung) ein bestimmter Ausdruck jetzt erzeugt - und das selbst den Experten, die den Standard schreiben, nicht klar ist. Mir kommen echt die Tränen, dass Ihr Euch in so viele neue Dinge einarbeiten müsst. Wilhelm M. schrieb: > Mir kommen echt die Tränen, dass Ihr Euch in so viele neue Dinge > einarbeiten müsst. Du beherrschst sämtliche Features von C++20? :-)
Gast
#6537949
Mark B. schrieb: > Du beherrschst sämtliche Features von C++20? :-) Der schlaue Programmierer lernt sie bei Bedarf anstatt sich jedes Mal über den bösen Fortschritt zu beklagen...
Gast
#6538052
Mark B. schrieb: > Wilhelm M. schrieb: >> Mir kommen echt die Tränen, dass Ihr Euch in so viele neue Dinge >> einarbeiten müsst. > > Du beherrschst sämtliche Features von C++20? :-) Die 2h, um einmal alle Änderungen zu überfliegen, sollte man haben. Den Rest kann man machen, wenn man es braucht oder die Zeit hat. Wilhelm M. schrieb: > Mir kommen echt die Tränen, dass Ihr Euch in so viele neue Dinge > einarbeiten müsst. Hängt schlicht davon ab, ob man für das "sich in viele neue Dinge einarbeiten" oder etwas anderes bezahlt wird, und ob man dafür eher eine Stunde oder drei Monate braucht. mh schrieb: > Die 2h, um einmal alle Änderungen zu überfliegen, sollte man haben. Sicherlich, aber die Konsequenzen daraus sind nochmal eine ganz andere Hausnummer.
Gast
#6538072
S. R. schrieb: > Sicherlich, aber die Konsequenzen daraus sind nochmal eine ganz andere > Hausnummer. Was sind denn die Konsequenzen "daraus"? Ich sehe Nichts, das große Konsequenzen hat, wenn es nicht einsetzt. mh schrieb: > Was sind denn die Konsequenzen "daraus"? > > Ich sehe Nichts, das große Konsequenzen hat, wenn es nicht einsetzt. Nun ja, mit concepts, auto überall, constexpr lambdas, ranges, und was da alles noch so an Kleinigkeiten dabei ist, sieht der Code doch schon sehr anders aus als das, was man mit C++11 so gebastelt hat. Bis man das in voller Konsequenz mal mental umgesetzt hat, dauerts schon länger als nur zwei Stunden. Aber new und delete gibts auch immer noch, wer will, kannn nach wie vor "C mit Klassen"-Code schreiben. Oliver mh schrieb: > Ich sehe Nichts, das große Konsequenzen hat, wenn es nicht einsetzt. Die Konsequenz daraus ist, das du die Chance verschenkst deinen Code (typ) sicherer zu machen ;-)
Gast
#6538327
Oliver S. schrieb: > mh schrieb: >> Was sind denn die Konsequenzen "daraus"? >> >> Ich sehe Nichts, das große Konsequenzen hat, wenn es nicht einsetzt. > > Nun ja, mit concepts, auto überall, constexpr lambdas, ranges, und was > da alles noch so an Kleinigkeiten dabei ist, sieht der Code doch schon > sehr anders aus als das, was man mit C++11 so gebastelt hat. Bis man das > in voller Konsequenz mal mental umgesetzt hat, dauerts schon länger als > nur zwei Stunden. Es ging um C++20, also sind nur die Änderungen seit C++17 relevant. Und wie gesagt: mh schrieb: > Die 2h, um einmal alle Änderungen zu überfliegen, sollte man haben. Den > Rest kann man machen, wenn man es braucht oder die Zeit hat. Niemand erwartet, dass du das alle C++20 Änderungen von heute auf morgen perfekt benutzen kannst. Hans-Georg L. schrieb: > mh schrieb: >> Ich sehe Nichts, das große Konsequenzen hat, wenn es nicht einsetzt. > > Die Konsequenz daraus ist, das du die Chance verschenkst deinen Code > (typ) sicherer zu machen ;-) Kannst du genauer erklären, wann ICH eine Chance verschenkt habe? Oder was wolltest du mit dem Beitrag zum Ausdruck bringen? mh schrieb: > Ich sehe Nichts, das große Konsequenzen hat, wenn es nicht einsetzt. Wenn man es nicht einsetzt, dann bleibt man aber bei C++03 stehen. Also: Entweder lernt man die neuen Features, oder man benutzt sie halt nicht. mh schrieb: > Es ging um C++20, also sind nur die Änderungen seit C++17 relevant. Es ging um C++20 im Vergleich zu dem Stand vor C++11. mh schrieb: > Ich sehe Nichts, das große Konsequenzen hat, wenn es nicht einsetzt. Es geht nicht darum, ob ich es einsetze, sondern ob jemand anderes das in der gleichen Codebasis einsetzt, mit der ich arbeiten muss. Und selbst wenn ich einsetze heißt das noch lange nicht, dass der Rest des Teams damit arbeiten kann. Oliver S. schrieb: > Nun ja, mit concepts, auto überall, constexpr lambdas, ranges, und was > da alles noch so an Kleinigkeiten dabei ist, sieht der Code doch schon > sehr anders aus als das, was man mit C++11 so gebastelt hat. Schöne Zusammenfassung. Genau das macht modernes C++20 effektiv zu einer völlig anderen Programmiersprache als der, die ich vor garnicht so vielen Jahren mal als "C++" kennengelernt habe.
Gast
#6538394
Rolf M. schrieb: > mh schrieb: >> Ich sehe Nichts, das große Konsequenzen hat, wenn es nicht einsetzt. > > Wenn man es nicht einsetzt, dann bleibt man aber bei C++03 stehen. Also: > Entweder lernt man die neuen Features, oder man benutzt sie halt nicht. Warum erwähnst du jetzt C++03? Willst du wirklich aussagen, dass man entweder alle neuen Feauters einsetzt, oder sich auf einen fast 20 Jahre alten Standard beschränken muss? Es gibt nichts was da zwischen liegt? Ich kann mir nicht vorstellen, dass du das wirklich sagen willst. > mh schrieb: >> Es ging um C++20, also sind nur die Änderungen seit C++17 relevant. > > Es ging um C++20 im Vergleich zu dem Stand vor C++11. Dann verfolge die Kette mal bis zu dem Betrag, aus dem dieser Satz von mir stammt. Um es einfacher zu machen: mh schrieb: > Mark B. schrieb: >> Wilhelm M. schrieb: >>> Mir kommen echt die Tränen, dass Ihr Euch in so viele neue Dinge >>> einarbeiten müsst. >> >> Du beherrschst sämtliche Features von C++20? :-) > > Die 2h, um einmal alle Änderungen zu überfliegen, sollte man haben. Den > Rest kann man machen, wenn man es braucht oder die Zeit hat. Es ging also sehr wohl um C++20.
Gast
#6538402
S. R. schrieb: > mh schrieb: >> Ich sehe Nichts, das große Konsequenzen hat, wenn es nicht einsetzt. > > Es geht nicht darum, ob ich es einsetze, sondern ob jemand anderes das > in der gleichen Codebasis einsetzt, mit der ich arbeiten muss. Und > selbst wenn ich einsetze heißt das noch lange nicht, dass der Rest des > Teams damit arbeiten kann. Es ist jetzt also die Schuld des Standardkomitees, dass ihr euch im Team nicht auf ein gemeinsames Werkzeug einigen könnt? > Oliver S. schrieb: >> Nun ja, mit concepts, auto überall, constexpr lambdas, ranges, und was >> da alles noch so an Kleinigkeiten dabei ist, sieht der Code doch schon >> sehr anders aus als das, was man mit C++11 so gebastelt hat. > > Schöne Zusammenfassung. > > Genau das macht modernes C++20 effektiv zu einer völlig anderen > Programmiersprache als der, die ich vor garnicht so vielen Jahren mal > als "C++" kennengelernt habe. C++11 oder C++20. Wo sind plötzlich C++14 und C++17 geblieben? Habt ihr euch wirklich seit 6 Jahren nicht mehr weitergebildet? Dann kann es ja kein besonders wichtiges Werkzeug sein. mh schrieb: > Dann verfolge die Kette mal bis zu dem Betrag, > aus dem dieser Satz von mir stammt. Der Thread handelt von den "ganzen Erweiterungen von C++11/14/17". Die Beschränkung auf "die Unterschiede zwischen C++17 und C++20" kam tatsächlich von dir, hat aber sonst niemanden interessiert. ;-)
Gast
#6538424
S. R. schrieb: > mh schrieb: >> Dann verfolge die Kette mal bis zu dem Betrag, >> aus dem dieser Satz von mir stammt. > > Der Thread handelt von den "ganzen Erweiterungen von C++11/14/17". > > Die Beschränkung auf "die Unterschiede zwischen C++17 und C++20" kam > tatsächlich von dir, hat aber sonst niemanden interessiert. ;-) Wenn Mark B. schreibt "Du beherrschst sämtliche Features von C++20", kommt das also plötzlich von mir? mh schrieb: > S. R. schrieb: >> mh schrieb: >>> Dann verfolge die Kette mal bis zu dem Betrag, >>> aus dem dieser Satz von mir stammt. >> >> Der Thread handelt von den "ganzen Erweiterungen von C++11/14/17". >> So sehe ich das auch. >> Die Beschränkung auf "die Unterschiede zwischen C++17 und C++20" kam >> tatsächlich von dir, hat aber sonst niemanden interessiert. ;-) > > Wenn Mark B. schreibt "Du beherrschst sämtliche Features von C++20", > kommt das also plötzlich von mir? Es kam nicht von dir, aber du hast dich auf die Reduktion darauf eingelassen. Wenn man generisch programmiert ist es auf jeden Fall sinnvoll die C++20 Constraints und concepts sich anzuschauen. Was wollen wir? [] Wir wollen eine Programmiersprache, die sich nicht ändert, damit wir unser Denken nicht ändern müssen. [] Wir wollen eine Programmiersprache, die vollständig abwärtskompatibel ist, damit der alte Code immmer noch compiliert werden kann, und ohne neue Bugs läuft. Alte Bugs sollen erhalten bleiben. [] Wir wollen ein Programmiersprache, die top-modern ist, und die allerneuesten Features, die diskutiert werden, inkludiert. [] Wir wollen eine Programmiersprache, die nicht aufgebläht ist, weil regelmäßig alte Features entfernt werden. [] Wir wollen eine Programmiersprache, die möglichst wenig Features hat, damit sie leicht zu lernen ist. [] Wir wollen eine Programmiersprache, die immer den schnellsten Maschinen-Code und auch sonstwie den effizientesten Ressourcengebrauch liefert. [] Wir wollen ein Programmiersprache, dessen Syntax uns persönlich am besten passt. [] Wir wollen eine Programmiersprache, die sich nicht ändert, damit wir nichts neues lernen müssen. [] Wir wollen eine Programmiersprache, die nicht von einem Gremium definiert wird, damit wir uns nicht engagieren müssen. [] Wir wollen eine Programmiersprache, die wir erlernen können, ohne zu lernen bzw. ihr Historie oder ihre grundlegenden Ideen zu verstehen. [] ... [] ... Schaut aus, wie im richtigen Leben ;-)
Gast
#6538601
[x] Wir wollen C89 ("ANSI-C") weil wir das im Studium lernen mussten und
zu faul sind irgendwas anderes zu lernen. Außerdem Simulink weil das so
schön bunt ist.
Im übrigen ist das hier Diskutierte eher ein Problem der "alten Säcke" als der "jungen Hüpfer". Die Jungen kommen oft aus eine Script-Welt o.ä. und sind "überglücklich" über die Möglichkeiten des "modernen C++". Die Umständlichkeiten des "alten C++" erzählt man einmal, und dann lassen sie die auch sofort gerne links liegen.
Gast
#6538644
Also entweder gefällt mir ausnahmslos alles an C++, oder ich bin lernfaul, alt oder sonst wie minderbemittelt. Ist das in etwa richtig zusammengefasst? Wenn’s für dich so passt, dann ja. Oliver Eumel schrieb: > Also entweder gefällt mir ausnahmslos alles an C++, oder ich bin > lernfaul, alt oder sonst wie minderbemittelt. Ist das in etwa richtig > zusammengefasst? Wenn Du das darin liest, dann sicherlich ja ;-) Wilhelm M. schrieb: > Im übrigen ist das hier Diskutierte eher ein Problem der "alten Säcke" > als der "jungen Hüpfer". Die Jungen kommen oft aus eine Script-Welt o.ä. > und sind "überglücklich" über die Möglichkeiten des "modernen C++". Die > Umständlichkeiten des "alten C++" erzählt man einmal, und dann lassen > sie die auch sofort gerne links liegen. Ich bin so ein alter Sack, der mit programmieren angefangen hat als der 8080 Assembler noch vom Lochstreifen eingelesen wurde, mit "klassischem" C++ später sein Geld verdient hat und schon ein Weilchen Rentner ist ;-). Wenn du keine Erfahrung hast wie man ein System in wieder verwendbare Klassen aufteilt nützen dir die tollsten Features einer Sprache nichts. Ob Erfahrungen aus der Script Welt dabei helfen sei mal dahin gestellt. Im Moment versuche ich meine C Programme für die STM32 MC auf C++ um zu stellen und da sind Klassen eher unwichtig und die neuen Features sehr willkommen. Allerdings unterstützt die STM Cube-IDE nur den gcc 9.3.1 und somit C++17 aber es lässt sich nur -std=c++14 einstellen. Diese blöden Eclipse IDEs sind alle so vermurkst, die Build Systeme und die Debugger Unterstützung sind untereinander nicht kompatibel. Den gcc scheint es aber nicht zu stören wenn man zusätzlich noch -std=c++17 hinzu fügt. Ich bin immer noch dabei zu lernen, auch wenn es langsamer geht ;-) Hans-Georg L. schrieb: > Im Moment versuche ich meine C Programme für die STM32 MC auf C++ um zu > stellen und da sind Klassen eher unwichtig und die neuen Features sehr > willkommen. So sehe ich es auch: OOP auf Mikrocontrollern in Embedded Systemen braucht man oft nicht, bzw. bringt für viele typische Anwedungsfälle (z.B. Abarbeiten eines Schnittstellenprotokolls) oft keine nennenswerten Vorteile gegenüber prozeduraler Programmierung. Aber C++ ist eben nicht nur OOP. Man sagt ja auch, es sei eine "multi-paradigm" Programmiersprache. Hans-Georg L. schrieb: > Im Moment versuche ich meine C Programme für die STM32 MC auf C++ um zu > stellen und da sind Klassen eher unwichtig und die neuen Features sehr > willkommen. Klassen sind an der Stelle sehr(!) wichtig. Und zwar als die Basis der Meta-Programmierung. Denn Meta-Funktionen F: type -> type sind im allgemeinen als Klassentemplates bzw. Spezialisierungen derselben realisiert. Was Du allerdings meinst mit Deiner Aussage ist ein Teilbereich der OOP, nämlich Laufzeitpolymorphie. Das mag für den µC Bereich eher weniger wichtig sein (in meinen Augen ist es das). Wobei es auch da Ersatz gibt, der auf µC besser geeignet ist. Mark B. schrieb: > Man sagt ja auch, es sei eine "multi-paradigm" > Programmiersprache. Genau: und klassische OOP ist nur ein Teil davon! Aber selbst von man klassische OOP nicht einsetzt, heißt dass nicht, dass Klassen (in C++) unnütz sind ... Wilhelm M. schrieb: > Hans-Georg L. schrieb: >> Im Moment versuche ich meine C Programme für die STM32 MC auf C++ um zu >> stellen und da sind Klassen eher unwichtig und die neuen Features sehr >> willkommen. > > Klassen sind an der Stelle sehr(!) wichtig. Und zwar als die Basis der > Meta-Programmierung. Denn Meta-Funktionen F: type -> type sind im > allgemeinen als Klassentemplates bzw. Spezialisierungen derselben > realisiert. > > Was Du allerdings meinst mit Deiner Aussage ist ein Teilbereich der OOP, > nämlich Laufzeitpolymorphie. Das mag für den µC Bereich eher weniger > wichtig sein (in meinen Augen ist es das). Wobei es auch da Ersatz gibt, > der auf µC besser geeignet ist. Wenn ich mich undeutlich ausdrücke darfst du mich gerne korrigieren ;-) Ich lerne gerne dazu ... Mein Bestreben war es erst einmal das C Konstrukt : RCC->AHB1ENR = GPIOA | 1<<GPIOB | 1<<GPIOC /*usw...*/ ; durch eine typsichere und einfach verständliche C++ Version zu ersetzen. Meine Version: AHB1_EnableClock(GPIOA_CLK,GPIOB_CLK,GPIOC_CLK); Meine Datentypen sind enums und die kann man in diesem Zusammenhang auch als Klassen sehen. Anbei noch ein Code Ausschnitt dazu. ps .. die enums lassen sich auch noch nach read/write only erweitern
Gast
#6539017
Hans-Georg L. schrieb: > Anbei noch ein Code Ausschnitt dazu. Zeile 40 enthält einen Fehler.
Gast
#6539029
Hans-Georg L. schrieb: > Anbei noch ein Code Ausschnitt dazu. In Zeile 53 ist auch ein Fehler. Hau wech den Scheiss schrieb: > Hans-Georg L. schrieb: > >> Anbei noch ein Code Ausschnitt dazu. > > Zeile 40 enthält einen Fehler. Danke. Das ist nur ein erster Versuch im Endeffekt möchte ich diese Declarationen wenn ich mir über die Strukturierung der namespaces klar bin, automatisch aus dem svd File erzeugen aber auch diese sind nicht unbedingt Fehlerfrei.
Gast
#6539039
Hans-Georg L. schrieb: > automatisch aus dem svd File erzeugen aber auch diese sind nicht > unbedingt Fehlerfrei. Vielleicht einen Plausibilitätscheck drüber laufen lassen, der auf doppelte vergebenen Addressen schaut. Misaligment für dword-Adressen wäre auch so ein Check der sich anbietet, aber letzteres sollte doch auch der Assembler finden und als Warning bemeckern. Vielleicht auch aus den pdf-docs mit tesseract rauspulen wenn man den mitgelieferten Headern nicht trauen kann. Hau wech den Scheiss schrieb: > Hans-Georg L. schrieb: >> automatisch aus dem svd File erzeugen aber auch diese sind nicht >> unbedingt Fehlerfrei. > > Vielleicht einen Plausibilitätscheck drüber laufen lassen, der auf > doppelte vergebenen Addressen schaut. > > Misaligment für dword-Adressen wäre auch so ein Check der sich anbietet, > aber letzteres sollte doch auch der Assembler finden und als Warning > bemeckern. Vielleicht auch aus den pdf-docs mit tesseract rauspulen wenn > man den mitgelieferten Headern nicht trauen kann. Assembler hat nichts gefunden nochmal mit datenblatt verglichen, das müsst jetzt stimmen Es geht übrigends um den STM32F411 (Blackpill) <code> namespace Regs { constexpr reg32_t RCC_BASE AHB1PERIPH_BASE + 0x3800UL; // RCC register constexpr reg32_t RCC_CR = RCC_BASE; constexpr reg32_t RCC_PLLCFGCR = RCC_BASE + 0x04U; constexpr reg32_t RCC_CFGCR = RCC_BASE + 0x08U; constexpr reg32_t RCC_CIR = RCC_BASE + 0x0CU; constexpr reg32_t RCC_AHB1RSTR = RCC_BASE + 0x10U; constexpr reg32_t RCC_AHB2RSTR = RCC_BASE + 0x14U; constexpr reg32_t RCC_APB1RSTR = RCC_BASE + 0x20U; constexpr reg32_t RCC_APB2RSTR = RCC_BASE + 0x24U; constexpr reg32_t RCC_AHB1ENR = RCC_BASE + 0x30U; constexpr reg32_t RCC_AHB2ENR = RCC_BASE + 0x34U; constexpr reg32_t RCC_APB1ENR = RCC_BASE + 0x40U; constexpr reg32_t RCC_APB2ENR = RCC_BASE + 0x44U; constexpr reg32_t RCC_AHB1LPENR = RCC_BASE + 0x50U; constexpr reg32_t RCC_AHB2LPENR = RCC_BASE + 0x54U; constexpr reg32_t RCC_APB1LPENR = RCC_BASE + 0x60U; constexpr reg32_t RCC_APB2LPENR = RCC_BASE + 0x64U; constexpr reg32_t RCC_BDCR = RCC_BASE + 0x70U; constexpr reg32_t RCC_CSR = RCC_BASE + 0x74U; constexpr reg32_t RCC_SSCGR = RCC_BASE + 0x80U; constexpr reg32_t RCC_PLLI2SCFGR = RCC_BASE + 0x84U; } </code> Hau wech den Scheiss schrieb: > Hans-Georg L. schrieb: >> automatisch aus dem svd File erzeugen aber auch diese sind nicht >> unbedingt Fehlerfrei. > > Vielleicht einen Plausibilitätscheck drüber laufen lassen, der auf > doppelte vergebenen Addressen schaut. > > Misaligment für dword-Adressen wäre auch so ein Check der sich anbietet, > aber letzteres sollte doch auch der Assembler finden und als Warning > bemeckern. Vielleicht auch aus den pdf-docs mit tesseract rauspulen wenn > man den mitgelieferten Headern nicht trauen kann. Guter Tip, das könnte ich dann alles in mein Programm einbauen das die svd Files einliest. Hans-Georg L. schrieb: > Wenn ich mich undeutlich ausdrücke darfst du mich gerne korrigieren ;-) > Ich lerne gerne dazu ... > > Mein Bestreben war es erst einmal das C Konstrukt : > RCC->AHB1ENR = GPIOA | 1<<GPIOB | 1<<GPIOC /*usw...*/ ; > durch eine typsichere und einfach verständliche C++ Version zu ersetzen. Wunderbar. Das ist der erste Schritt.
Ich habe Dein static_assert() mal durch ein adhoc-requirement ersetzt. DAs macht die Fehlermeldung ggf. intuitiver. Desweiteren ist es eher unüblich, die traits zu instanziieren und dann implizit nach bool zu koinvertieren.
Habe das mal kurz hier geändert, nur als Idee. Du könntest dann auch noch scoped-enums einsetzen. Statt extra Funktionen für set/clear einzuführen, kannst Du nach dem gleichen Muster ggf. die Op-|| und Op-&& für die Typen überladen. Ggf. sogar als template und per enable-if/concept ganz gezielt aktivieren für die Typen, für die Du das haben möchtest.
Gast
#6539232
Hans-Georg L. schrieb: >> Misaligment für dword-Adressen wäre auch so ein Check der sich anbietet, >> aber letzteres sollte doch auch der Assembler finden und als Warning >> bemeckern. Vielleicht auch aus den pdf-docs mit tesseract rauspulen wenn >> man den mitgelieferten Headern nicht trauen kann. > > Guter Tip, das könnte ich dann alles in mein Programm einbauen das die > svd Files einliest. Da könnte aber auch eine IMHO sinnvolle Erweiterung der Programmiersprache sein, das man Typen nicht nur entsprechend Bitbreite und Vorzeichen definiert, sondern auch nach dem 'Alignment'. Also Hier einen Typen für die Registeraddressen vorsehen der nur Konstanten endend auf 0x0, 0x4, 0x8 oder 0xC zulässt. Scripte zur Fehlersuche, -vermeidung über den Code einzusetzen scheint mir aber ein universeller Ansatz, der auch für andere Sprachen einsetzbar ist. Also generische Prüfscripte für jede Prozessorarchitektur (auch FPGA eigene Prozessoren) die den C/C++/? Code auf 'offensichtliche Merkwürdigkeiten' durchsucht. Die 'merkwürdigen Stellen' hatte ich schon in einer Minute drüberfliegen gefunden, das Raussuchen von Datenblatt und Vergleich hat dann ein Mehrfaches an Zeit gekostet.
Gast
#6539250
Hau wech den Scheiss schrieb: > Da könnte aber auch eine IMHO sinnvolle Erweiterung der > Programmiersprache sein, das man Typen nicht nur entsprechend Bitbreite > und Vorzeichen definiert, sondern auch nach dem 'Alignment'. Das haben C und C++ schon lange. Kann man seit C++11 (na sowas) auch explizit festlegen mit dem "alignas" Keyword. Allerdings ist der manuelle Zugriff auf beliebige Speicherstellen durch Umcasten von Adressen sowieso nicht vorgesehen und ein Missbrauch der Sprache, weshalb da auch die Adresse nicht geprüft wird. Hau wech den Scheiss schrieb: > Scripte zur Fehlersuche, -vermeidung über den Code einzusetzen scheint > mir aber ein universeller Ansatz, der auch für andere Sprachen > einsetzbar ist. Diese sind allerdings schwierig in komplexe Sprachen zu integrieren, weil man hier alle Sprachkonstrukte korrekt verarbeiten muss. Glücklicherweise kann man in C++ dank Metaprogrammierung und statischer Typisierung eine Menge Prüfungen direkt in der Sprache vornehmen, die dann bei jedem kompilier-Vorgang direkt vom Compiler geprüft werden, ganz ohne externe Skripte. Hier z.B. mit:
Hier zeigt sich der Nachteil der klassischen C-Programmierung: Diverse Funktionalität muss man durch externe Tools nachbilden (Fehlersuche, Code-Generierung), während man in mächtigeren Sprachen wie C++ diese Dinge einfach direkt schon integriert hat.
Gast
#6539264
Was mich immer wieder nervt ist, dass es praktisch unmöglich ist einfache Ausdrücke wie: GPIOA->BSS = 1<<5; So z.b. in Templates zu verpacken dass am Ende ein asm Zweizeiler dabei rauskommt auch wenn die Optimierung des Kompilers zum Debuggen ausgeschaltet ist. Mit eingeschalteter Optimierung ist das kein Problem. Oder anders gefragt, wie baut man z.B. eine Gpio Klasse so, dass sie nicht während des Debuggens 5 mal langsamer wird? Leider ist es bis heute so, will man beim Debuggen und im Release annähernd gleiche Resultate beim erzeugten Code, geht um ein C—Macro auch 2021 immer noch kein Weg vorbei. Ich lasse mich aber gern eines besseren Belehren. temp schrieb: > Leider ist es bis > heute so, will man beim Debuggen und im Release annähernd gleiche > Resultate beim erzeugten Code, geht um ein C—Macro auch 2021 immer noch > kein Weg vorbei. Ich lasse mich aber gern eines besseren Belehren. Du kannst doch sicher -Og benutzen. Das reicht aus, um die template-calls (inline) zu optimieren. Die obige Lösung kannst Du natürlich verbessern, und möglichst viel zur Compilezeit erledigen:
(Oder Du schreibst noch eine Meta-Funktion für den |-Op, ist wegen constexpr aber unnötig, etwa static_or<...>). Mit dem static_or dann:
bzw:
Auf die Typ-Prüfungen habe ich jetzt verzichtet, kann man aber ja noch obigem Muster ebenfalls einbauen. Programmierer schrieb: ... >
>
Werde ich einbauen Danke.
Wilhelm M. schrieb: > temp schrieb: >> Leider ist es bis >> heute so, will man beim Debuggen und im Release annähernd gleiche >> Resultate beim erzeugten Code, geht um ein C—Macro auch 2021 immer noch >> kein Weg vorbei. Ich lasse mich aber gern eines besseren Belehren. > > Du kannst doch sicher -Og benutzen. Das reicht aus, um die > template-calls (inline) zu optimieren. > > Die obige Lösung kannst Du natürlich verbessern, und möglichst viel zur > Compilezeit erledigen: > > [c] > template<reg32_t adr, auto ... Args> > constexpr void enable() { > constexpr reg32_t mask = (... | Args); > *reinterpret_cast<volatile reg32_t*>(adr) |= mask; > } Wilhelm M. schrieb: > template<reg32_t ra,typename T, typename ... Args> > requires((... && std::is_same<Args, T>{})) > constexpr void set_bit(Args ... args ) { > // static_assert((... && std::is_same<Args, T>())); // > parameter test > reg32_t mask =(... | args); // folding OR > *reinterpret_cast<volatile reg32_t*>(ra) |= mask; // set bitmask > }; > > Ich habe Dein static_assert() mal durch ein adhoc-requirement ersetzt. > DAs macht die Fehlermeldung ggf. intuitiver. > requires ist c++20 und wie schon geschrieben ist mein compiler auf c++17 begrenzt aber eine sinnvolle Fehlermeldung könnte ich noch ausgeben > Desweiteren ist es eher unüblich, die traits zu instanziieren und dann > implizit nach bool zu koinvertieren. > template<reg32_t ra,typename T, typename ... Args> > constexpr void clear_bit(Args ... args ) { > static_assert((... && std::is_same_v<Args, T>)); // parameter > test > reg32_t mask =(... | args); // folding OR > *reinterpret_cast<volatile reg32_t*>(ra) &= ~mask; // clear > bitmask > }; > Finde den Unterschied nicht so leicht für ältere Augen ;-) > Du könntest dann auch noch scoped-enums einsetzen. Das wollte ich sowieso und vorsichtshalber den underlying typ auf unsigned ändern. Nicht das der Compiler, durch Bit-Schiebereien, irgendwann auf die Idee kommt Bit31 als Vorzeichen aufzufassen. > Statt extra Funktionen für set/clear einzuführen, kannst Du nach dem > gleichen Muster ggf. die Op-|| und Op-&& für die Typen überladen. Ggf. > sogar als template und per enable-if/concept ganz gezielt aktivieren für > die Typen, für die Du das haben möchtest. Ich bin ehrlich gesagt kein großer Freund davon erstmal alles zusammen zu fassen und dann wieder mit if zu zerlegen. Mal sehen.. es gibt ja noch andere Registertypen. Hans-Georg L. schrieb: > Finde den Unterschied nicht so leicht für ältere Augen ;-)
statt
Hans-Georg L. schrieb: > Ich bin ehrlich gesagt kein großer Freund davon erstmal alles zusammen > zu fassen und dann wieder mit if zu zerlegen Nicht if, sondern enable-if.
Gast
#6539364
Mit -Og hab ich auch schon gespielt. Kennen aber auch nicht alle Compiler. Das kann aber auch nicht die Lösung sein. Mit #pragma kann man auch für bestimmte Teile im Code eine gezielt anderen Optimierung verwenden. Allerdings brachte das bisher keinen Erfolg. Ich mache jetzt schon nur bei den Dateien die ich Debugge den Schalter auch an, sonst passt ein Release Code von 20k schon nicht mehr in 32k Flash. Trotzdem nervt mich das einfach nur und hindert mich auch daran Lobeshymnen auf C++ im embedded Bereich zu singen. Was nützt das alles, wenn man zwar schöne Programme schreiben kann, die am Ende aber nicht vernünftig debugbar sind oder beim Debuggen 3 mal so groß. Bei der PC Programmierung stört mich das nicht. Hans-Georg L. schrieb: > requires ist c++20 und wie schon geschrieben ist mein compiler auf c++17 > begrenzt Ist das ein gcc? Und c++2a kann der noch nicht? Das requires dannst Du ggf. auch durch ein enable-if ersetzen, um die Instantiierung aus dem overload-set zu entfernen. Sorry, ich wollte diesen Thread nicht für mich kapern aber ich denke es geht immer noch um allgemeines C++ Wissen. Wilhelm M. schrieb: > Hans-Georg L. schrieb: >> requires ist c++20 und wie schon geschrieben ist mein compiler auf c++17 >> begrenzt > > Ist das ein gcc? Und c++2a kann der noch nicht? > > Das requires dannst Du ggf. auch durch ein enable-if ersetzen, um die > Instantiierung aus dem overload-set zu entfernen. Es ist wie geschrieben ein gcc 9.3.1 der sich mit STM CUBE-IDE (Eclipse) maximal auf c++14 stellen lässt. Aber man kann zusätzlich c++17 einfügen, was er dann auch benutzt. Das funktioniert auch mit -std=c++2a. :-) gibt es auch eine Option zum Removen einer anderen Option ? Also um das -std=c++14 los zu werden. Hans-Georg L. schrieb: > Es ist wie geschrieben ein gcc 9.3.1 Sorry, hatte ich nicht gelesen. Im übrigen ist das Compilieren des Gcc aus dem git-repo kein Problem.
Gast
#6539415
temp schrieb: > Was nützt das alles, wenn man zwar > schöne Programme schreiben kann, die am Ende aber nicht vernünftig > debugbar sind oder beim Debuggen 3 mal so groß. Du könntest zur Entwicklung/Debugging einen größeren Controller mit mehr Flash nehmen und dann für die Serienproduktion wo es auf's Geld ankommt den kleinstmöglichen. Mit __attribute__((always_inline)) kann man sich auch schon gut behelfen, oder indem man nur einzelne Dateien ohne Optimierung kompiliert. IMO ist es aber auch gar nicht so schlimm optimierten Code zu debuggen. Der Cursor springt halt ein bisschen lustig herum. Hans-Georg L. schrieb: > gibt es auch eine Option zum Removen einer anderen Option ? Also um das > -std=c++14 los zu werden. Das ist ein Problem des Cube-Eclipse-Plugins, nicht des Compilers. Da musst du dich an die dazu zuständigen Programmierer wenden. Andere Plugins bieten in dem Auswahlfeld zumindest ein leeres Feld an. Oliver Oliver S. schrieb: > Hans-Georg L. schrieb: >> gibt es auch eine Option zum Removen einer anderen Option ? Also um das >> -std=c++14 los zu werden. > > Das ist ein Problem des Cube-Eclipse-Plugins, nicht des Compilers. Da > musst du dich an die dazu zuständigen Programmierer wenden. > > Andere Plugins bieten in dem Auswahlfeld zumindest ein leeres Feld an. > > Oliver Unter Window->Preferences->StmCube->Build gibt es dieses Leerfeld. Unter den Project->settings aber dann nicht mehr. Dieses Plugin hat mich schon Nerven gekostet. Ich benutze die Cube IDE nur weil man damit problemlos zwischen ST-Link und Segger J-Link umschalten kann und der Build mit dem CubeMX Code kompatibel ist was bei anderen, wo man seinen eigenen Compiler einbinden kann leider nicht funktioniert. Und anpassen kann man bei allen selbst nichts, sondern muss irgendwo betteln das es einer macht.
Gast
#6539510
Hans-Georg L. schrieb: > Ich benutze die Cube IDE > nur weil man damit problemlos zwischen ST-Link und Segger J-Link > umschalten kann Das geht mit dem GNU-MCU-Eclipse Plugin auch. Hans-Georg L. schrieb: > und der Build mit dem CubeMX Code kompatibel ist was > bei anderen, wo man seinen eigenen Compiler einbinden kann leider nicht > funktioniert. Wieso das? Die CubeIDE nutzt auch nur den normalen GCC-ARM-Embedded. Wenn man den separat herunterlädt (und ggf. in eine beliebige IDE einbindet) kann man damit auch den CubeMX-generierten Code kompilieren. Wenn das bei dir nicht klappt hast du irgendwas falsch gemacht (Makros vergessen oder so). Programmierer schrieb: > Hans-Georg L. schrieb: >> Ich benutze die Cube IDE >> nur weil man damit problemlos zwischen ST-Link und Segger J-Link >> umschalten kann > > Das geht mit dem GNU-MCU-Eclipse Plugin auch. > > Hans-Georg L. schrieb: >> und der Build mit dem CubeMX Code kompatibel ist was >> bei anderen, wo man seinen eigenen Compiler einbinden kann leider nicht >> funktioniert. > > Wieso das? Die CubeIDE nutzt auch nur den normalen GCC-ARM-Embedded. > Wenn man den separat herunterlädt (und ggf. in eine beliebige IDE > einbindet) kann man damit auch den CubeMX-generierten Code kompilieren. > Wenn das bei dir nicht klappt hast du irgendwas falsch gemacht (Makros > vergessen oder so). Es geht nicht um den Code sondern die .(c)project files. Irgendwann hast du eine Sammlung von .project files die untereinander nicht kompatibel sind. Diese Baustelle möchte ich nicht mehr öffnen ;-)
Gast
#6539631
Hans-Georg L. schrieb: > Es geht nicht um den Code sondern die .(c)project files. Irgendwann hast > du eine Sammlung von .project files die untereinander nicht kompatibel > sind. Achso. Die sind aber bei Verwendung des GNU-MCU-Plugin flugs angelegt. Sich deswegen auf die STM32CubeIDE festzulegen ist Jammern auf hohem Niveau.
Gast
#6539814
Programmierer schrieb: > IMO ist es aber auch gar nicht so schlimm > optimierten Code zu debuggen. Der Cursor springt halt ein bisschen > lustig herum. Ne, das ist absoluter Mist. Dann nehme ich lieber printf und überhaupt keinen Debugger. Was nützt es mir einen Breakpoint zu setzen, der sich nicht an die Regeln im Code hält weil er halt durch die Optimierung entweder garnicht mehr da ist oder nichts mehr mit dem Quellcode zu tun hat. Sollten die Werkzeugen nicht dazu da sein mir die Arbeit zu erleichtern? Aber nein jetzt muss man sich wieder Gedanken darum machen wie und wann der Compiler optimiert? Schöne neue constexpr Welt. Das kann der Präprozessor seit 50 Jahren aber besser... Und das ganze Geschwafel von Typesicherheit ist überflüssig wie ein Kropf. Jedenfalls im embedded Bereich. Wenn jemand solche Klötze wie boost anbietet, mag das seine Berechtigung haben. Das paradoxe an C++ ist hat, mit jeder Erweiterung (c++11/14/17) wurde die Tipparbeit immer mehr. Endlos lange Zeilen die mehr verwirren als nützen. Jetzt macht man gerade wieder die Rolle Rückwärts und macht neue Erweiterungen damit es wieder kürzer wird. Aber schön, es wollen ja schließlich Leute dafür bezahlt werden sich immer wieder neue Formen für den Kopf einer for(;;) einfallen zu lassen. Am Ende entscheidet sich jeder Entwickler für seine persönliche Vorliebe, kriegt er dann mal fremden Code vorgeschmissen ist das dann erst mal wie eine neue Sprache. Ich bin beeindruckt.
Gast
#6539833
Jaja, früher war alles besser. Hab gar keine Lust den ganzen Blödsinn zu
widerlegen. Nur für andere Mitleser: Ein strategisch platziertes
'__BKPT();' bzw. '__asm__ volatile ("bkpt" : : : "memory");' kann im
Notfall, wenn normale Breakpoints gar nicht funktionieren wollen,
helfen.
temp schrieb: > Und das ganze Geschwafel von Typesicherheit ist überflüssig wie ein > Kropf. Selten so gelacht. temp schrieb: > Das paradoxe an C++ > ist hat, mit jeder Erweiterung (c++11/14/17) wurde die Tipparbeit immer > mehr. Das stimmt nicht, zumindest nicht in dieser Pauschalität. 7 der 9 von mir oben genannte Vorzüge von C++≥11 Yalu X. schrieb: > Die für mich wichtigsten positiven Punkte sind: führen zu kompakterem und übersichtlicherem Code. Die verbleibenden 2 (Punkte 6 und 7) erfordern zwar etwas mehr Tipparbeit, helfen aber bei der Aufdeckung von Programmierfehlern, deren Suche sonst i.Allg. mehr Zeit beansprucht als die paar zusätzlich zu tippenden Zeichen.
Gast
#6540130
Programmierer schrieb: > Jaja, früher war alles besser. Hab gar keine Lust den ganzen Blödsinn zu > widerlegen. Nur für andere Mitleser: Ein strategisch platziertes > '__BKPT();' bzw. '__asm__ volatile ("bkpt" : : : "memory");' kann im > Notfall, wenn normale Breakpoints gar nicht funktionieren wollen, > helfen. Das hat nichts mit früher war alles besser zu tun. Solange das "heute ist alles viel besser" solche Klimmzüge erfordert die vorher nicht nötig waren ist das Neue eben nicht besser. Und wenn das ganze schon bei der Implementierung einer einfachen Gpio-Klasse dazu führt, dass ich schlechter Debuggen kann, ist und bleibt es Mist. Wie gesagt, vielleicht bin ich ja zu blöd und ihr wisst es alle besser. Dann aber bitte ein Beispiel liefern wie man dem Compiler beibringen kann seine Berechnungen zur Compilierzeit zu machen ohne in der Datei wo es verwendet wird expliziet einen Optimierungslevel angeben zu muessen. Das hab ich mal kurz mit dem Simulator vom Segger Embedded Studio probiert. Bitte nur überprüfte Vorschläge machen.
Sowas sollte dabei rauskommen.
und nicht sowas bei Optimierung kleiner 2
Wilhelm M. schrieb: > Mit dem static_or dann: > *reinterpret_cast<volatile reg32_t*>(Regs::RCC_AHB1ENR) = > static_or_v<CRC_CLK,GPIOA_CLK,GPIOB_CLK,GPIOC_CLK,GPIOD_CLK>; > > bzw: > GPIOA->BSS = static_or_v<...>; > > Auf die Typ-Prüfungen habe ich jetzt verzichtet, kann man aber ja noch > obigem Muster ebenfalls einbauen. Jetzt muss mir einmal jemand verraten welchen Vorteil es bring so eine Konstruktion als Ersatz von
zu verwenden. Und sowas wie "Regs::RCC_AHB1ENR" setzt voraus, dass alle Registerdefinitionen der CPU neu geschrieben werden müssen. Einen Vorteil hat das dann, man lernt seinen Controller gut kennen...
Gast
#6540166
muss mein Beispiel nochmal korrigieren:
der erzeugt Code sieht so aus:
ohne Optimierungslevel werden auch wieder richtige Funktionscalls erzeugt. das "gute Alte" würde so aussehen:
und erzeugt unabhängig von der Optimierung den gleichen kurzen Assemblercode. Quintessenz: Man erkauft sich mit den Vorteilen des "guten Neuen" neue Hürden die beim "verschmäten Alten" garnicht erst auftreten.
Gast
#6541242
Was mir nicht so gut gefällt, ist daß die "uniform initialisation" nicht der alten Initialisierung gleichwertig ist: Das ist OK:
Das nicht:
Siehe auch: https://www.youtube.com/watch?v=-AQfQFcXac8 :-) Gerade Ast schrieb: > Was mir nicht so gut gefällt, ist daß die "uniform initialisation" nicht > der alten Initialisierung gleichwertig ist: Und das ist m.E. gut so! Gerade Ast schrieb: > Siehe auch: > https://www.youtube.com/watch?v=-AQfQFcXac8 :-) Da wird einem ja schlecht: new / delete ;-) Wilhelm M. schrieb: > Gerade Ast schrieb: >> Was mir nicht so gut gefällt, ist daß die "uniform initialisation" nicht >> der alten Initialisierung gleichwertig ist: > > Und das ist m.E. gut so! Das kann man so sehen oder auch nicht. "Gerade Ast", meine Wenigkeit und viele andere sehen das offensichtlich anders als du. Wie ich oben schon schrieb und das Beispiel von "Gerade Ast" deutlich zeigt, ist die "uniform initialization" alles andere als "uniform". Rätselfrage: Was gibt folgendes Programm aus?
Das kommt u.a, darauf an, ob MyClassX ein int ist... Oliver Yalu X. schrieb: > std::vector<MyClass1> v1{2}; och, da können wir doch gleich weitermachen:
Oliver S. schrieb: > Das kommt u.a, darauf an, ob MyClassX ein int ist... Richtig, oder ob MyClassX einen Konstruktor mit int-Argument hat oder ob int in MyClassX konvertierbar ist ... Kurz: Verwendet man die uniform Initialization (v1 und v2), muss man sich in myclasses.h die Typ- bzw. Klassendefinition von MyClassX anschauen. Mit der klassischen Initialisierung (v3 und v4) ist das Verhalten sofort ohne weitere Nachforschungen erkennbar. Wilhelm M. schrieb: > std::vector<MyClass1> v1(2, 3); Was ist daran Besonderes? Bei zwei int-Argumenten ist das erste die Anzahl der Elemente, und damit ist v1.size() auch ohne Kenntnis der Klassendefinition eindeutig bestimmt, oder nicht? Yalu X. schrieb: > Wilhelm M. schrieb: >> std::vector<MyClass1> v1(2, 3); > > Was ist daran Besonderes? Ich finde die "uniform initialization" konsistenter:
Yalu X. schrieb: > Kurz: Verwendet man die uniform Initialization (v1 und v2), muss man > sich in myclasses.h die Typ- bzw. Klassendefinition von MyClassX > anschauen. Mit der klassischen Initialisierung (v3 und v4) ist das > Verhalten sofort ohne weitere Nachforschungen erkennbar. Was Du hier zitierst, ist nicht ein Thema der uniform-initialization, sondern es ist Design-Defekt von std::vector<>. Dieser entsteht durch Abwärtskompatibilität, was m.E. auch ein sehr hohes Gut ist. Der ctor std::vector<T>(int) bzw. std::vector<T>(int, T) gehören nicht in die Schnittstelle (zumindest wenn T=int; das sieht man auch daran, dass dann die Bedeutung der beiden int nicht klar ist -> Strong-Types). Da die jedoch vorher da waren, war es ein Fehler, den std::vector<T>(std::initializer_list<T>) hinzuzunehmen (Dies ist ja auch schon oft diskutiert worden, aber wegen Abwärtskompatibiliät ... nun ja). Eine Variante wäre es gewesen, in einem anderen Namensraum ein korrekte Variante von vector<> anzubieten. Wilhelm M. schrieb: > Was Du hier zitierst, ist nicht ein Thema der uniform-initialization, > sondern es ist Design-Defekt von std::vector<>. Ob man den Design-Defekt dem std::vector oder der uniform Initialization zuschreibt, ist IMHO Ansichtssache. Fest steht, dass dieser "Defekt" vor der Einführung der uniform Initialization nicht in Erscheinung trat. > Der ctor std::vector<T>(int) bzw. std::vector<T>(int, T) gehören nicht > in die Schnittstelle (zumindest wenn T=int; Ich finde den Konstruktor zur Initialisierung des Vektors mit n gleichen Elementen ganz praktisch. > das sieht man auch daran, dass dann die Bedeutung der beiden int nicht > klar ist -> Strong-Types). Dann wäre also jede Funktion mit zwei oder mehr Argumenten gleichen Typs defekt? Dann müssten deiner Ansicht nach auch die pow- und die atan2-Funktion und sogar die Operatoren für Subtraktion und Division abgeschafft werden? Alternativ könnte man spezielle Datentypen für Basis, Exponent, y-Koordinate, x-Koordinate, Minuend, Subtrahend, Dividend und Divisor einführen. Ich bin mir aber sicher: Wenn dies geschehen würde, würde C++ 90% seiner Gefolgschaft verlieren. > Da die jedoch vorher da waren, war es ein Fehler, den > std::vector<T>(std::initializer_list<T>) hinzuzunehmen Diese ist aber eine der wirklich wertvollen Neuerungen von C++, auf die ich nicht verzichten wollte. Sie beißt sich auch überhaupt nicht mit bestehenden Features der Sprache. Der Konflikt entsteht erst im Zusammenhang mit der – IMHO weitgehend nutzlosen – uniform Initialization. Letztere wurde nicht vor sondern zusammen mit der initializer_list (beides C++11) eingeführt, deswegen lag hier der große Fehler. Diesen Fehler umschiffe ich, indem ich die uniform Initialization einfach nicht nutze. Es wäre schön, wenn jeder, mit dessen Quellcode ich arbeiten muss, ebenso handeln würde. Wilhelm M. schrieb: > Eine Variante wäre es gewesen, in einem anderen Namensraum ein korrekte > Variante von vector<> anzubieten. Eine sehr viel einfachere und elegantere Variante wäre es gewesen, die uniform Initialization komplett wegzulassen. Für mich scheint das ein Feature zu sein, dass einfach nicht zu Ende gedacht wurde. Wilhelm M. schrieb: > Ich finde die "uniform initialization" konsistenter: > { > std::vector<int> v1(); // ups > std::vector<int> v2(3); > std::vector<int> v3(3, 2); // ist das [2, 2, 2] oder [3, 3] ? > std::vector<int> v4(2, 3); > // std::vector<int> v5(1, 2, 3); // warum geht das nicht? Ist doch einfach. Der erste Parameter ist hier immer die Größe. Das ist auch ganz unabhängig vom Elementtyp des vectors. > } > { > std::vector<int> v1{}; > std::vector<int> v2{3}; > std::vector<int> v3{3, 2}; > std::vector<int> v4{2, 3}; > std::vector<int> v5{1, 2, 3}; > } Wie mache ich einen vector, der 100 default-initialisierte Elemente hat? Wilhelm M. schrieb: > Was Du hier zitierst, ist nicht ein Thema der uniform-initialization, > sondern es ist Design-Defekt von std::vector<>. Dieser entsteht durch > Abwärtskompatibilität, was m.E. auch ein sehr hohes Gut ist. Das ist eben die Crux. Ja, Abwärtskompatibilität ist wichtig, und ja, viele der neuen Features haben durchaus ihre Berechtigung, aber es macht die Sprache auch sehr unübersichtlich. Yalu X. schrieb: > Wilhelm M. schrieb: >> Was Du hier zitierst, ist nicht ein Thema der uniform-initialization, >> sondern es ist Design-Defekt von std::vector<>. > > Ob man den Design-Defekt dem std::vector oder der uniform Initialization > zuschreibt, ist IMHO Ansichtssache. Ja. Offensichtlich sind wir da schon lange unterschiedlicher Ansicht. Wir hatten in anderen Threads schon desöfteren darüber geredet. > Fest steht, dass dieser "Defekt" vor > der Einführung der uniform Initialization nicht in Erscheinung trat. Ja. Für den Grund: s.o. Dafür gab es andere: most-vexing-parse, keine list-initialisierung, ... >> Der ctor std::vector<T>(int) bzw. std::vector<T>(int, T) gehören nicht >> in die Schnittstelle (zumindest wenn T=int; > > Ich finde den Konstruktor zur Initialisierung des Vektors mit n gleichen > Elementen ganz praktisch. Ich auch ;-) Das kann ja auch so bleiben. Falls Du das anders verstanden hast, dann hast Du mich oben falsch verstanden. Es ging um den mehrstelligen ctor. >> das sieht man auch daran, dass dann die Bedeutung der beiden int nicht >> klar ist -> Strong-Types). > > Dann wäre also jede Funktion mit zwei oder mehr Argumenten gleichen Typs > defekt? Grundsätzlich: ja. Mehrstellige Funktionen mit denselben, unspezifischen Datentypen sind m.E. zu vermeiden. > Dann müssten deiner Ansicht nach auch die pow- und die > atan2-Funktion und sogar die Operatoren für Subtraktion und Division > abgeschafft werden? Nein. Du musst nicht gleich das Kinde mit dem Bade ausschütten. >> Da die jedoch vorher da waren, war es ein Fehler, den >> std::vector<T>(std::initializer_list<T>) hinzuzunehmen > > Diese ist aber eine der wirklich wertvollen Neuerungen von C++, auf die > ich nicht verzichten wollte. Sie beißt sich auch überhaupt nicht mit > bestehenden Features der Sprache. Genau. > Der Konflikt entsteht erst im > Zusammenhang mit der – IMHO weitgehend nutzlosen – uniform > Initialization. Und da bin ich eben anderer Meinung: s.o.. Die beiden ctoren (s.o.) hätte man eben abschaffen müssen, was natürlich nicht geht. Da die Sache aber seit Urzeiten verbockt ist, hätte man es anders lösen müssen. > Diesen Fehler umschiffe ich, indem ich die uniform > Initialization einfach nicht nutze. Es wäre schön, wenn jeder, mit > dessen Quellcode ich arbeiten muss, ebenso handeln würde. Ich mache es anders herum wie Du weißt: ich / wir arbeiten nur mit uniform-initialisation. > Wilhelm M. schrieb: >> Eine Variante wäre es gewesen, in einem anderen Namensraum ein korrekte >> Variante von vector<> anzubieten. > > Eine sehr viel einfachere und elegantere Variante wäre es gewesen, die > uniform Initialization komplett wegzulassen. Für mich scheint das ein > Feature zu sein, dass einfach nicht zu Ende gedacht wurde. Der Fehler ist m.E. gewesen, dass man eben die Konsequenzen speziell im std::vector<> u.a. nicht bedacht hat. Das kann passieren. Da das Problem aber schon sehr früh entdeckt und bemängelt wurde. hätte man es auf verschiedene Weise korrigieren können. Das war der fatale Folgefehler. Bei den Concepts etwa hat man ja wegen ähnlicher Probleme aus dem TS die function-style-concepts wieder entfernt - und zwar kurz vor knapp! Rolf M. schrieb: > Wilhelm M. schrieb: >> Ich finde die "uniform initialization" konsistenter: >> { >> std::vector<int> v1(); // ups >> std::vector<int> v2(3); >> std::vector<int> v3(3, 2); // ist das [2, 2, 2] oder [3, 3] ? >> std::vector<int> v4(2, 3); >> // std::vector<int> v5(1, 2, 3); // warum geht das nicht? > > Ist doch einfach. Der erste Parameter ist hier immer die Größe. Das ist > auch ganz unabhängig vom Elementtyp des vectors. > >> } >> { >> std::vector<int> v1{}; >> std::vector<int> v2{3}; >> std::vector<int> v3{3, 2}; >> std::vector<int> v4{2, 3}; >> std::vector<int> v5{1, 2, 3}; >> } > > Wie mache ich einen vector, der 100 default-initialisierte Elemente hat? Vorschlag:
> Wilhelm M. schrieb: >> Was Du hier zitierst, ist nicht ein Thema der uniform-initialization, >> sondern es ist Design-Defekt von std::vector<>. Dieser entsteht durch >> Abwärtskompatibilität, was m.E. auch ein sehr hohes Gut ist. > > Das ist eben die Crux. Ja, Abwärtskompatibilität ist wichtig, und ja, > viele der neuen Features haben durchaus ihre Berechtigung, aber es macht > die Sprache auch sehr unübersichtlich. s.o. meine "Wunschliste" ;-) Also ich bleibe bei C, im embedded Bereich.
Gast
#6542307
Tom K. schrieb: > Also ich bleibe bei C, im embedded Bereich. Da spricht auch nichts dagegen. Allerdings war das hier nicht das Thema. Ich nutze C++, allerdings nicht um jeden Preis. Gerade wenn so ein kleiner Controller nur 20k RAM hat dürfte die excessive Verwendung der STL sowieso ausgeschlossen sein. Eigentlich alles was mit dynamischen Speicher arbeitet. Und wenn man sich schon darauf einlässt, sollte man auch genau wissen wie die STL intern arbeit um die Grenze ausloten zu können. Nach oben gibt es sicher Controller die über genug Resource verfügen. Wenn es in diese Größenordnung geht nehme ich aber lieber gleich einen Raspi o.ä. mit ordentlichem Betriebssystem. Da kann man dann auch im C++ Baukasten in die Vollen greifen. Ups, eben sehe ich dass der ganze Thread unter PC-Programmierung eingeordnet ist. Da stellt sich die gesamte Frage nicht. Auch die Debugproblematik bzw. gezielte Optimierung ist da kein Thema. Auf einem kleinen Controller aber schon. temp schrieb: > Ich nutze C++, allerdings nicht um jeden Preis. Gerade wenn so ein > kleiner Controller nur 20k RAM hat dürfte die excessive Verwendung der > STL sowieso ausgeschlossen sein. Gerade für kleine µC nutze nur noch C++, natürlich dann ohne stdlib. Dadurch werden viel mehr Fehler schon zur Compilezeit aufgedeckt bzw. verhindert.
Gast
#6543016
temp schrieb: > template<eGpioPort ePort, uint32_t bitPosi> > class GpioPin {} leider ist das kacke, weil dann alle Interfaces die GpioPin entgegen nehmen auch templates sein müssen.
Das erzeugt bei GCC mit Optimierung (inkl. LTO) optimalen Code, wenn das Pin Objekt als const angelegt wird. Dies klappt auch, wenn das Objekt in andere Objekte via Konstruktor injiziert wird. Dummerweise failed der GCC, sobald die Klasse einen Konstruktor hat. Deshalb mache ich bei Gpio eine Ausnahme und benutze kein übergeordnetes Interface. interessant schrieb: > leider ist das kacke, weil dann alle Interfaces die GpioPin entgegen > nehmen auch templates sein müssen. Der sog. CodeBloat, den viele befürchten, ist in der Praxis (bei realen Programmen und nicht nur Mini-Beispielen) viel geringen - wenn überhaupt vorhanden, und nicht das Gegenteil eintritt - als man denkt. Verzichtet man komplett auf dyn. Polymorphie und bei der Modellierung von HW auf die Erzeugung von Instanzen, macht stattdessen nur stat. Polymorphie und header-only hat man m.E. nur Vorteile.
Gast
#6543219
interessant schrieb: > temp schrieb: >> template<eGpioPort ePort, uint32_t bitPosi> >> class GpioPin {} > > leider ist das kacke, weil dann alle Interfaces die GpioPin entgegen > nehmen auch templates sein müssen. Das war hier nicht die Frage, das Beispiel sollte kurz bleiben. Es ging in dem Beispiel darum, dass es Kacke ist, dass es keinen (mir bekannten Weg) gibt, solchen einfachen Templates (Einzeiler) mitzuteile, dass sie bitte auch beim Debuggen inline in ein paar wenige Assembler Statements übersetzt werden. Also genau das machen was mit einem C-Macro schon immer ging. Leider konnte mir noch keiner das Gegenteil beweisen. interessant schrieb: > Das erzeugt bei GCC mit Optimierung (inkl. LTO) optimalen Code, wenn > das Pin Objekt als const angelegt wird. Das ist jetzt aber nicht dein Ernst? Und dann HAL_xx Aufrufe? Noch schlimmer gehts nicht. Ich greife dein Beispiel aber mal auf:
Auch hier gibt es keinen Weg bei ausgeschalteter Optimierung das gleiche Ergebnis wie mit dem Macro zu erzeugen. Das Problem ist ja, vieles wird heute in C++ in die Header verlagert. Viel Funktionalität von der man davon ausgeht es ist getesteter Code. Die Innereien davon will man meistens nicht debuggen sondern nur seinen eigenen Code der das benutzt. Und genau dafür um das zu steuern gibt es irgendwie keine Lösung. Es ist ja genauso als wenn ich zum Debuggen unter Windows bzw. Linux immer mit den Debug-Versionen alles Systemlibs arbeiten würde. Auch auf dem PC komme ich immer ins Fluchen, da die Einzelschrittabarbeitung von Code im Debugger fast unmöglich ist. Ständig landet man da in den Untiefen der STL, die man ja eigentlich überhaupt nicht debuggen will. In dieser Hinsicht hat das jetzte Jahrzehnt jedenfalls keinen Fortschritt gebracht. Wilhelm M. schrieb: > interessant schrieb: >> leider ist das kacke, weil dann alle Interfaces die GpioPin entgegen >> nehmen auch templates sein müssen. > > Der sog. CodeBloat, den viele befürchten, ist in der Praxis (bei realen > Programmen und nicht nur Mini-Beispielen) viel geringen - wenn überhaupt > vorhanden, und nicht das Gegenteil eintritt - als man denkt. Verzichtet > man komplett auf dyn. Polymorphie und bei der Modellierung von HW auf > die Erzeugung von Instanzen, macht stattdessen nur stat. Polymorphie und > header-only hat man m.E. nur Vorteile. Da bin ich der gleichen Meinung und Bloat kann man auch mit C erzeugen. z.B. die STM-HAL erzeugt nicht so knapp Bloat im RAM.
Gast
#6543248
temp schrieb: > Ständig landet man da in den Untiefen der STL, die man ja eigentlich > überhaupt nicht debuggen will. Also da musst du den Debugger richtig konfigurieren. Mit lldb und gdb geht das solala - ich habe den Eindruck da trotzdem öfter mal in einer zu skippenden Datei zu landen, muss aber meine Konfig nochmal checken. https://stackoverflow.com/questions/5676241/tell-gdb-to-skip-standard-files https://stackoverflow.com/questions/13211452/tell-lldb-to-ignore-files temp schrieb: snip ... > Auch hier gibt es keinen Weg bei ausgeschalteter Optimierung das gleiche > Ergebnis wie mit dem Macro zu erzeugen. > Das Problem ist ja, vieles wird heute in C++ in die Header verlagert. > Viel Funktionalität von der man davon ausgeht es ist getesteter Code. > Die Innereien davon will man meistens nicht debuggen sondern nur seinen > eigenen Code der das benutzt. Und genau dafür um das zu steuern gibt es > irgendwie keine Lösung. Es ist ja genauso als wenn ich zum Debuggen > unter Windows bzw. Linux immer mit den Debug-Versionen alles Systemlibs > arbeiten würde. Auch auf dem PC komme ich immer ins Fluchen, da die > Einzelschrittabarbeitung von Code im Debugger fast unmöglich ist. > Ständig landet man da in den Untiefen der STL, die man ja eigentlich > überhaupt nicht debuggen will. In dieser Hinsicht hat das jetzte > Jahrzehnt jedenfalls keinen Fortschritt gebracht. Ich habe das gerade mit meinem geposteten Code und mit dem gcc 9.3.1 -std=c++17 -Og gestestet. Beim debugger single step landet er direct in meinem "set_bit" mit der Einschränkung das ich mir nicht den parameter pack angucken kann. Damit kann ich aber leben. Kommt halt darauf an was man will. Ich will z.b. meine selbst geschriebene lib debuggen , aber die std libs nicht. @Wilhelm M requires kennt der gcc erst ab version 10. ps. ich habe den Code nochmal angehängt damit man nicht lange suchen muss.
Gast
#6543360
Hans-Georg L. schrieb: > Damit kann ich aber leben. Kommt halt darauf an was > man will. Ich will z.b. meine selbst geschriebene lib debuggen , aber > die std libs nicht. Die selbst geschriebenen Libs debuggt man aber nur solange man sie schreibt. Irgendwann wirst du die ja auch mal benutzen. Deinen Code oben würde ich nicht mal ansatzweise in Erwägung ziehen. Alles was nicht mit den Definitionen aus den Headern des Controllers auskommt, kommt für mich nicht in Frage. Ebensowenig wie irgendwelche HAL Libs wie bei STM. Aber das sind perönliche Vorlieben. Al Fine schrieb: > Also da musst du den Debugger richtig konfigurieren. Danke, das kannte ich noch nicht. Ist aber trotzdem eine ganz schöne Orgie. Sowas zu steuern gehört aber meines Erachtens nach in den C++ Standard und nicht in die Konfiguration des gdb oder wer auch immer. Hans-Georg L. schrieb: > @Wilhelm M > requires kennt der gcc erst ab version 10. Bis Du sicher? Auch mit -fconcepts-ts oder -fconcepts? Aber ich weiß es nicht mehr genau, ab welcher Version, ist schon sooo lange her. Trotzdem gebe ich Dir den guten Rat, auf eine aktuelle Version des gcc zu gehen, wenn Du den Weg - der super sinnvoll ist - weiter verfolgen willst. Denn Concepts sind DAS feature für stat. Polymorphie. Begreife Klassentemplates als Meta-Funktionen, die Du mit Hilfe von Concepts durch partielle Spezialisierung "überladen" kannst: Du kannst also eine Meta-Funktion (partielle Spezialisierung) anhand eines Concepts für einen template-typ-parameter (oder nttp) aktivieren. Das ist die statische Analogie zu single-dispatch bzw. zu tag-dispatching. Hans-Georg L. schrieb: > Beim debugger single step landet er direct in > meinem "set_bit" mit der Einschränkung das ich mir nicht den parameter > pack angucken kann. Sollte im mangled-name stehen ... temp schrieb: > Deinen Code oben würde ich nicht mal ansatzweise in Erwägung ziehen. > Alles was nicht mit den Definitionen aus den Headern des Controllers jeder hat seine Vorlieben ;-)
Das mit der Namen-Differenz Header zum Datenblatt stört mich bei der HAL und der LL. Wilhelm M. schrieb: > Trotzdem gebe ich Dir den guten Rat, auf eine aktuelle Version des gcc > zu gehen, wenn Du den Weg - der super sinnvoll ist - weiter verfolgen > willst. Denn Concepts sind DAS feature für stat. Polymorphie. > > Begreife Klassentemplates als Meta-Funktionen, die Du mit Hilfe von > Concepts durch partielle Spezialisierung "überladen" kannst: Du kannst > also eine Meta-Funktion (partielle Spezialisierung) anhand eines > Concepts für einen template-typ-parameter (oder nttp) aktivieren. Das > ist die statische Analogie zu single-dispatch bzw. zu tag-dispatching. Ich habe dem gcc 10.2 von der ARM-Seite auf der Platte und in Eclipse als User defined Toolchain in eine Liste eintragen können aber es gibt keine Möglichkeit das zu aktivieren. Und im Moment reicht mir das auch so wie es ist, die Lib wird auch nicht so bleiben wie sie ist. Was mir von den neusten Errungenschaften von C++ das Leben leichter macht nehme ich gerne.
Gast
#6543600
Hans-Georg L. schrieb: > Das mit der Namen-Differenz Header zum Datenblatt stört mich bei der HAL > und der LL. Wenn es am Ende darauf hinausläuft, alle Registerdefinitionen des Controllers neu in eine andere Syntax zu pressen, kann ich mir kaum vorstellen, dass da in überschaubarer Zeit eine halbwegs fehlerfreie Lib rauskommt. Und wozu? Damit du dann die Fehler in deiner Lib suchst und nicht mehr im Anwendungsprogramm. Typischer Fall von C++ um jeden Preis. Und dann noch zusätzlich HAL oder LL. Ich kann nur vermuten, du bist im akademischen Bereich tätig. Geld verdienen geht damit nicht und wenn Hobby, dann muss das Hobby darin bestehen LIBs zu bauen. temp schrieb: > Hans-Georg L. schrieb: >> Das mit der Namen-Differenz Header zum Datenblatt stört mich bei der HAL >> und der LL. > > Wenn es am Ende darauf hinausläuft, alle Registerdefinitionen des > Controllers neu in eine andere Syntax zu pressen, kann ich mir kaum > vorstellen, dass da in überschaubarer Zeit eine halbwegs fehlerfreie Lib > rauskommt. Das kommt darauf an, woher die ursprünglichen Definitionen kommen. Beim AVR gibt's z.B. XML-Dateien, die die Register und andere Dinge beschreiben, aus denen die Header generiert werden. Daraus könnte man auch entsprechende C++-Header automatisiert generieren.
Gast
#6543772
Rolf M. schrieb: > Das kommt darauf an, woher die ursprünglichen Definitionen kommen. Vom Hersteller natürlich. Rolf M. schrieb: > Daraus könnte man > auch entsprechende C++-Header automatisiert generieren. Auch das macht sich nicht von allein. Ich würde an sowas micht mal einen Gedanken verschwenden. Rolf M. schrieb: > temp schrieb: >> Hans-Georg L. schrieb: >>> Das mit der Namen-Differenz Header zum Datenblatt stört mich bei der HAL >>> und der LL. >> >> Wenn es am Ende darauf hinausläuft, alle Registerdefinitionen des >> Controllers neu in eine andere Syntax zu pressen, kann ich mir kaum >> vorstellen, dass da in überschaubarer Zeit eine halbwegs fehlerfreie Lib >> rauskommt. > > Das kommt darauf an, woher die ursprünglichen Definitionen kommen. Beim > AVR gibt's z.B. XML-Dateien, die die Register und andere Dinge > beschreiben, aus denen die Header generiert werden. Daraus könnte man > auch entsprechende C++-Header automatisiert generieren. Für ARM gibt's dafür sogar Doku: https://www.keil.com/pack/doc/CMSIS/SVD/html/index.html temp schrieb: > Rolf M. schrieb: >> Das kommt darauf an, woher die ursprünglichen Definitionen kommen. > > Vom Hersteller natürlich. > > Rolf M. schrieb: >> Daraus könnte man >> auch entsprechende C++-Header automatisiert generieren. Gibt es beim den ARM MC auch nennt sich svd Files und die werden auch vom Debugger benutzt um SFR Register an zu zeigen. > > Auch das macht sich nicht von allein. Ich würde an sowas micht mal einen > Gedanken verschwenden. Kein Hexenwerk so was ähnliches habe ich schon öfter gemacht. Das macht aber erst Sinn wenn ich meine Zielstruktur gefunden habe und da bin ich gerade dabei. temp schrieb: > Hans-Georg L. schrieb: >> Das mit der Namen-Differenz Header zum Datenblatt stört mich bei der HAL >> und der LL. > > Wenn es am Ende darauf hinausläuft, alle Registerdefinitionen des > Controllers neu in eine andere Syntax zu pressen, kann ich mir kaum > vorstellen, dass da in überschaubarer Zeit eine halbwegs fehlerfreie Lib > rauskommt. Und wozu? Damit du dann die Fehler in deiner Lib suchst und > nicht mehr im Anwendungsprogramm. Typischer Fall von C++ um jeden Preis. > Und dann noch zusätzlich HAL oder LL. Ich kann nur vermuten, du bist im > akademischen Bereich tätig. Geld verdienen geht damit nicht und wenn > Hobby, dann muss das Hobby darin bestehen LIBs zu bauen. Hättest du nicht nur vermutet und den Thread auch gelesen ... Aber extra für dich noch einmal. Ich habe lange Zeit meine Brötchen mit klassischem C++ verdient und bin seit ein paar Jährchen Rentner. Jetzt beschäftige ich mich eben mit meta-Programmierung weil mir das einfach Spaß macht.
Gast
#6543829
Hans-Georg L. schrieb: > Jetzt > beschäftige ich mich eben mit meta-Programmierung weil mir das einfach > Spaß macht. Ist doch kein Problem, wenn du deine Erfüllung darin siehst. Damit verfolgst du halt andere Ziele als die meisten hier.
Gast
#6543895
> [C] > class GpioPin2 > { > public: > GPIO_TypeDef *pPort; > uint8_t pos; > > GpioPin2( GPIO_TypeDef * pP, uint8_t p) { pPort=pP; pos=p; > } > constexpr inline void Set() const { pPort->BSRR=1<<pos; } > constexpr inline void Clr() const { pPort->BSRR=1<<(pos+16); } > }; > Auch hier gibt es keinen Weg bei ausgeschalteter Optimierung das gleiche > Ergebnis wie mit dem Macro zu erzeugen. Ähh doch, siehe: https://godbolt.org/z/KfzexM Man braucht lediglich always_inline Attribute + lokale O3 Optimierung zu verwenden, was ich in einem solchen Fall für legitim halten würde. Der erzeugte Maschinencode ist für beide Funktionen sowohl für O0 als auch O3 identisch. Aber dann ist der Maschinencode mit O0 immer noch 2.5 mal so lang ggü. O3, von daher verstehe ich deine Ansicht nicht so ganz... Ich werde mal bei ST ein Ticket aufmachen, dass die HAL_GPIO_WritePin Implementierung in den Header verlegt werden soll. temp schrieb: > Rolf M. schrieb: >> Das kommt darauf an, woher die ursprünglichen Definitionen kommen. > > Vom Hersteller natürlich. Entsprechend dem darauf folgenden Beispiel hätte man eigentlich darauf kommen können, dass gemeint war, ob da wirklich einer den ganzen Header von Hand geschrieben oder vielleicht auch aus etwas generiert hat, aus dem man genauso gut den C++-Header generieren kann. > Rolf M. schrieb: >> Daraus könnte man >> auch entsprechende C++-Header automatisiert generieren. > > Auch das macht sich nicht von allein. Doch, wenn man einmal den Generator geschrieben hat (was nun auch nicht arg schwer ist), macht sich das von allein. Dafür sind Code-Generatoren da. Das machen sie für den C-Code ja auch. > Ich würde an sowas micht mal einen Gedanken verschwenden. Ich halte es dagegen für sinnvoll und sehe nichts, was dagegen spricht.
Beitrag #6543903 wurde von einem Moderator gelöscht.
Hans-Georg L. schrieb: > @Wilhelm M > requires kennt der gcc erst ab version 10. Ich hatte Dir die notwendigen Optionen genannt. Hast Du die eingesetzt? Im CompilerExplorer mit gcc-9.3 und -std=c++17 -Og -fconcepts geht das. Sogar ab Version 7.1.
Gast
#6543992
interessant schrieb: > Ähh doch, siehe: https://godbolt.org/z/KfzexM > Man braucht lediglich always_inline Attribute + lokale O3 Optimierung zu > verwenden, was ich in einem solchen Fall für legitim halten würde. > > Der erzeugte Maschinencode ist für beide Funktionen sowohl für O0 als > auch O3 identisch. Stell deinen Beispielcode als Beweis hier rein oder halt den Mund. Und nein, always_inline ist leider nicht die Lösung und locale O3 Optimierung auch nicht. Solange du nicht über das Zitieren meines Codes hinauskommst nehme ich dich nicht für voll. interessant schrieb: > Der erzeugte Maschinencode ist für beide Funktionen sowohl für O0 als > auch O3 identisch. > > Aber dann ist der Maschinencode mit O0 immer noch 2.5 mal so lang ggü. > O3, von daher verstehe ich deine Ansicht nicht so ganz... Aha, identischer Maschinencode der 2,5mal länger ist. Fällt dir da nichts ein?
Gast
#6544018
temp schrieb: >> Ähh doch, siehe: https://godbolt.org/z/KfzexM Sorry, ich rudere zurück und bitte um Entschuldigung. Den Code im Onlinecompiler hatte ich nicht gesehen, da bei mir der Link zerst nicht ging.
Gast
#6544039
temp schrieb: > interessant schrieb: >> Ähh doch, siehe: https://godbolt.org/z/KfzexM >> Man braucht lediglich always_inline Attribute + lokale O3 Optimierung zu >> verwenden, was ich in einem solchen Fall für legitim halten würde. So, ich hab das natürlich probiert. Deine locale O3 Optimierung bring leider genau nichts. Das liegt daran, dass da wo du das notiert hat, kein Code erzeugt wird. Macht man die locale Optimierung da wo es verwendet wird (aLed.Set() aLed.Clr()) oder in deinem Beispiel für die gesamte Funktion a() oder b() geht das. Leider ist das aber keine Option, da ich das Gegenteil erreichen will. a() oder b() vernünftig debuggen ohne beim Singelstep in die Internas der Klasse Gpio zu springen. Es wäre wirklich eine riesen Hilfe, wenn die locale Optimierung auch bei Headern oder Klassendefinitionen funktionieren würde. Oder noch viel besser in wenn der Sprachstandard so etwas hergeben würde. Wilhelm M. schrieb: > Hans-Georg L. schrieb: >> @Wilhelm M >> requires kennt der gcc erst ab version 10. > > Ich hatte Dir die notwendigen Optionen genannt. Hast Du die eingesetzt? > > Im CompilerExplorer mit gcc-9.3 und -std=c++17 -Og -fconcepts > geht das. Sogar ab Version 7.1. -fconcepts war der Zauberspruch ;-) -std=c++2a wie zuerst vorgeschlagen, hat nicht funktioniert.
Gast
#6544084
Programmierer schrieb: > Hau wech den Scheiss schrieb: >> Eben. Warum irgendwelche modischen Neuerungen durchdrücken, wenn es >> weder die Manpower dafür gibt, noch irgendwelche Verbesserungen an der >> Sicherheit aka Kundenzufriedenheit zu erwarten sind. > > Worauf bezieht sich das jetzt? Neue Sprachfeatures wie z.B. Lambdas > bedeuten einfachere und schnellere Entwicklung und Wartung, und dadurch > geringere Entwicklungskosten und billigere Endprodukte, und billig macht > Kunden zufrieden. Ganz ehrlich: was ist der Vorteil von Lambdas. Der Nachteil ist halt dass die Lambda Funktion nicht einfach als Funktion getestet werden kann (ohne Copy-Paste), sondern nur im Kontext der verwendeten Funktion. Minimaler Vorteil ist ein leicht geringerer Schreibaufwand.
Gast
#6544105
lalala schrieb: > Ganz ehrlich: was ist der Vorteil von Lambdas. Der Nachteil ist halt > dass die Lambda Funktion nicht einfach als Funktion getestet werden kann > (ohne Copy-Paste), sondern nur im Kontext der verwendeten Funktion. > Minimaler Vorteil ist ein leicht geringerer Schreibaufwand. Die Dinger können Variablen aus ihrem Kontext capturen. Wenn man nicht nur eine Funktion sondern auch noch eine struct mit 4 Variablen oder so dazu braucht relativiert sich das mit dem "minimal". lalala schrieb: > Ganz ehrlich: was ist der Vorteil von Lambdas. Der Nachteil ist halt > dass die Lambda Funktion Lambda-Funktionen gibt es nicht. Was Du meinst, ist eine Lambda-Expression, die ein closure generiert, vulgo function-object. Gerade für µC finde ich lambda-expression in der Form als IIFE (immediate invoked function expression) extrem nützlich, um komplexe Initialisierungen für read-only Objekte (const) durchzuführen:
Ein einfaches Beispiel das o.g. einzusetzen, ist die Berechung von LUTs. Oder
(inkl. Rücksetzen, o.ä.). Ansonsten sind die lambda-expressions natürlich überall dort extrem praktisch, wo man sonst mit Funktionszeigern oder allg. Funktionsobjekten in Form von expliziten Klassen arbeiten musste (etwa stdlib-Algos). Hans-Georg L. schrieb: > -fconcepts war der Zauberspruch ;-) Stand auch schon ganz oben drin ;-) Hast wohl übersehen. lalala schrieb: > Ganz ehrlich: was ist der Vorteil von Lambdas. Der Nachteil ist halt > dass die Lambda Funktion nicht einfach als Funktion getestet werden kann > (ohne Copy-Paste), sondern nur im Kontext der verwendeten Funktion. > Minimaler Vorteil ist ein leicht geringerer Schreibaufwand. Hauptvorteil ist die deutlich erhöhte Übersichtlichkeit des Code, weil ich einen Zweizeiler nicht irgendwo weit weg als separate Funktion definieren muss, nur weil es halt eine Funktion sein muss, sondern gleich dorthin schreiben, wo er verwendet wird.
Gast
#6544203
Rolf M. schrieb: > Hauptvorteil ist die deutlich erhöhte Übersichtlichkeit des Code, weil > ich einen Zweizeiler nicht irgendwo weit weg als separate Funktion > definieren muss, nur weil es halt eine Funktion sein muss, sondern > gleich dorthin schreiben, wo er verwendet wird. Das hielt sich eigentlich in Grenzen, weil man ja überall einfach eine Klasse/struct definieren konnte (auch lokal). Aber solche Funktionsobjekte selbst zu schreiben war halt doch immer Aufwand. [code] void fn() { // ... struct S { S(int someValue) { //bla } bool operator()(int n) { // bla } // blub... }; algorithm(begin, end, S(4)); } interessant schrieb: >> [C] >> class GpioPin2 >> { >> public: >> GPIO_TypeDef *pPort; >> uint8_t pos; >> >> GpioPin2( GPIO_TypeDef * pP, uint8_t p) { pPort=pP; pos=p; >> } >> constexpr inline void Set() const { pPort->BSRR=1<<pos; } >> constexpr inline void Clr() const { pPort->BSRR=1<<(pos+16); } >> }; >> Auch hier gibt es keinen Weg bei ausgeschalteter Optimierung das gleiche >> Ergebnis wie mit dem Macro zu erzeugen. > > Ähh doch, siehe: https://godbolt.org/z/KfzexM > Man braucht lediglich always_inline Attribute + lokale O3 Optimierung zu > verwenden, was ich in einem solchen Fall für legitim halten würde. > > Der erzeugte Maschinencode ist für beide Funktionen sowohl für O0 als > auch O3 identisch. > > Aber dann ist der Maschinencode mit O0 immer noch 2.5 mal so lang ggü. > O3, von daher verstehe ich deine Ansicht nicht so ganz... > > Ich werde mal bei ST ein Ticket aufmachen, dass die HAL_GPIO_WritePin > Implementierung in den Header verlegt werden soll. Wer aus dem Code-Schnippsel tatsächlich alles rausholen will(*) , der könnte auf das Schieben verzichten und das für's "Löschen" zuständigen Register BRR benutzen. Zumindest "unoptimiert" ist das schneller. Außerdem kann man da auch schön sehen, daß zu wissen, was die HW kann (oder welchen Algorithmus man verwendet) wichtiger ist, als den Maschinencode direkt zu schreiben. (*) auf einem CortexM3 bringt das mit >O0 natürlich nicht wirklich was. Aber das zu verstehen setzt Kenntnisse des Thumb(2) Befehlssatzes voraus.
Gast
#6544308
temp schrieb: > So, ich hab das natürlich probiert. Deine locale O3 Optimierung bring > leider genau nichts.Leider ist das aber keine Option, da ich das Gegenteil > erreichen will. a() oder b() vernünftig debuggen ohne beim Singelstep in > die Internas der Klasse Gpio zu springen. Stimmt, die O3 bringt nichts, aber das always_inline schon. Dein Problem verstehe ich trotzdem nicht. Wer zum Geier single stepped seinen gesamten Code? Wenn da eine Funktion "pinA.set()" steht, wendet man step over an, denn das ist trivial code den man einmal schreibt und dann nie wieder debuggt. Single stepping macht man erst, wenn man verzweifelt einen Hardfault Fehler sucht :D lalala schrieb: > Ganz ehrlich: was ist der Vorteil von Lambdas. Der Nachteil ist halt > dass die Lambda Funktion nicht einfach als Funktion getestet werden kann > (ohne Copy-Paste), sondern nur im Kontext der verwendeten Funktion. > Minimaler Vorteil ist ein leicht geringerer Schreibaufwand. Die Lambda-Ausdrücke kommen ursprünglich aus der funktionalen Programmierung und finden nach und nach auch Einzug in imperative Programmiersprachen. In Funktionalsprachen dienen sie primär dazu, 1. zusammengehörige Dinge im Quellcode näher zusammenzurücken und damit die Übersichtlichkeit zu steigern 2. für Funktionen, deren Bedeutung auf einen Blick erfasst werden kann, den Funktionsnamen einzusparen 3. als angenehmen Nebeneffekt den Schreibaufwand zu verringern Diese Dinge sind aber nur bei sehr einfachen Funktionen relevant. Funktionen, die mehr als einen Einfachen Ausdruck enthalten, werden praktisch immer ganz normal mit Namen definiert. Da C++ keine lokalen Funktionsdefinitionen (also Funktionsdefinitionen innerhalb einer anderen Funktion) in der klassischen Notation erlaubt¹, kommt hier noch ein weiterer wesentlicher Aspekt hinzu: 4. Funktionen lokal zu definieren Dabei geht es nicht nur um die Sichtbarkeitsbeschränkung dieser Funktionen, sondern vor allem darum, in der lokalen Funktion auf lokale Variablen der umgebenden Funktion zugreifen zu können. Dazu muss die lokale Funktion nicht notwendigerweise anonym sein. Möchte man die Funktion benennen, weist man den Lambda-Ausdruck einfach einer Variable mit passendem Namen zu:
Aus dem (in C++ local nicht erlaubten) klassischen Funktionskopf
wird also
was ja gar nicht einmal so viel anders aussieht. Würde man localFunc global definieren, hätte sie keinen Zugriff auf x. Man müsste deswegen x als zweites Argument (zusätzlich zu y) übergeben, was aber insbesondere bei der Verwendung als Callback-Funktion nicht immer möglich ist, weil sich dadurch die Funktionssignatur ändert. Alternativ kann man die Funktion in ein callable Object packen: Al Fine schrieb: > void fn() { > // ... > > struct S { > S(int someValue) { //bla } > bool operator()(int n) { // bla } > // blub... > }; > > algorithm(begin, end, S(4)); > } So (oder so ähnlich) werden die Lambda-Ausdrücke intern repräsentiert. Die [...](...)-Schreibweise ist willkommener syntaktischer Zucker dafür. Witzigerweise sind wegen des o.g. 4. Punkts Lambda-Ausdrücke in C++ weit weniger verzichtbar als in den funktionalen Sprachen, in denen sie ursprünglich implementiert wurden, zumal es dort für viele typische Anwendungen von Lambda-Ausdrücken Ersatzschreibweisen gibt, die noch einmal kürzer und prägnanter sind. ────────────── ¹) GCC unterstützt lokale Funktionsdefinitionen als Erweiterung in C, aber nicht in C++. Yalu X. schrieb: > So (oder so ähnlich) werden die Lambda-Ausdrücke intern repräsentiert. Nicht der Lambda-Ausdruck wird so repräsentiert, sondern das Closure, also das Funktionsobjekt. Also das Ergebnis des Lambda-Ausdrucks. Ja, natürlich das Ergebnis. 'tschuldigung für die unpräzise Ausdrucksweise :)
Gast
#6544606
Carl D. schrieb: > Wer aus dem Code-Schnippsel tatsächlich alles rausholen will(*) > , der könnte auf das Schieben verzichten und das für's "Löschen" > zuständigen Register BRR benutzen. Zumindest "unoptimiert" ist das > schneller. Beweis das mal. Das ändert rein garnichts. Das Schieben mit Konstanten erfolgt doch nicht zur Laufzeit. Das Berechnet der Compiler zur Laufzeit. Und am Ende bleibt eine Zuweisung eines Registers mit einer Konstannten. Aber diese Diskussion geht am Ziel vobei. Ich suche nicht nach einer Lösung für genau das Problem, sondern kritisieren den aktuellen Zustand von C++ in dieser Hinsicht. interessant schrieb: > Wer zum Geier single stepped seinen gesamten Code? > Wenn da eine Funktion "pinA.set()" steht, wendet man step over an, denn > das ist trivial code den man einmal schreibt und dann nie wieder > debuggt. > > Single stepping macht man erst, wenn man verzweifelt einen Hardfault > Fehler sucht :D Wer bestimmt wann man was macht? Du nicht! Es geht hier ums Prinzip und nicht um dieses konkrete Beispiel. Aber mal ein Beispiel.
wenn ich im Singelstep im ersten Aufruf in testfunc() reinspringe lande ich auch sofort darin. strlen() ist eine Funktion aus der optimierten Lib und ich lande niemals in der Sourcen von strlen(). Anders die Variante mit dem std::string. Hier lande ich erst mal in den Headern davon und muss mich da durch hangeln bis ich irgendwann mal in der testfunc() lande. Sofort kommen jetzt wieder Schlauschweine die messerscharf schließen, man kann doch einen Breakpoint in testfunc() setzen. Alles richtig und wird sicher auch gemacht. Schön ist aber was anderes. Hinzukommt, eine strlen() bleibt optimiert ob ich das Programm debugge oder nicht. Wie std::string in Maschinencode übersetzt wird ist aber vom Optimierungslevel abhängig. Je mehr Metaprogrammiererei in den C++ Standard-Libs verwendet wird, desto mehr unterscheiden sich die Debug- und Releasevarianten eines Programms. Für mich ist und bleibt es ein Rückschritt. temp schrieb: > Für mich ist und bleibt es > ein Rückschritt. Du debug-st einfach zuviel ;-) Verwende mehr compiletime-Konstrukte, Strong-Types, etc, u.s.w. und Deine "Debugging-Experience" wird sich massiv verändern. temp schrieb: > Carl D. schrieb: >> Wer aus dem Code-Schnippsel tatsächlich alles rausholen will(*) >> , der könnte auf das Schieben verzichten und das für's "Löschen" >> zuständigen Register BRR benutzen. Zumindest "unoptimiert" ist das >> schneller. > > Beweis das mal. > Das ändert rein garnichts. Das Schieben mit Konstanten erfolgt doch > nicht zur Laufzeit. Das Berechnet der Compiler zur Laufzeit. Wo steht da, daß diese Klasse nur "constexpr" instanziiert werden kann? Das "constexpr" vor dem Konstruktor sagt nur, daß diese Klasse in compiletime Code instanziiert werden kann. BTW, das "constexpr" zu erzwingen heißt (ab C++20) "consteval". Daß man auf einem M3/4/... das Shiften umsonst bekommt, das ändert nicht an der Hauptaussage, daß man erst wissen sollte, was man tut und erst dann die Frage kommt "mit welchem Werkzeug". Aber was soll's. Jeder wie er will. Es verbietet niemand, da wo man hin will einen breakpoint zu setzen ;-)
Gast
#6544641
Wilhelm M. schrieb: > Du debug-st einfach zuviel ;-) Verwende mehr compiletime-Konstrukte, > Strong-Types, etc, u.s.w. und Deine "Debugging-Experience" wird sich > massiv verändern. Wenn das alles ist was an Argumenten bleibt hat sich jede weitere Diskussion erübrigt. temp schrieb: > Wilhelm M. schrieb: >> Du debug-st einfach zuviel ;-) Verwende mehr compiletime-Konstrukte, >> Strong-Types, etc, u.s.w. und Deine "Debugging-Experience" wird sich >> massiv verändern. > > Wenn das alles ist was an Argumenten bleibt hat sich jede weitere > Diskussion erübrigt. Das sind äußerst gewichtige Argumente: Code, der nicht compiliert, den braucht man nicht zu debuggen ;-)
Gast
#6544654
Carl D. schrieb: > Wo steht da, daß diese Klasse nur "constexpr" instanziiert werden kann? > Das "constexpr" vor dem Konstruktor sagt nur, daß diese Klasse in > compiletime Code instanziiert werden kann. BTW, das "constexpr" zu > erzwingen heißt (ab C++20) "consteval". > > Daß man auf einem M3/4/... das Shiften umsonst bekommt, das ändert nicht > an der Hauptaussage, daß man erst wissen sollte, was man tut und erst > dann die Frage kommt "mit welchem Werkzeug". > > Aber was soll's. Jeder wie er will. Hast du es immer noch nicht kapiert? Ich habe das als simples nachvollziehbares Beispiel benutzt. Selbst wenn ich das als reales Problem hätte würde ich mit Sicherheit nicht hier nach einer Lösung fragen. Hans-Georg L. schrieb: > Es verbietet niemand, da wo man hin will einen breakpoint zu setzen ;-) Herr lass Hirn regnen. So langsam glaube ich, ich bin hier bei selbst ernannten C++ Gurus gelandet die von sich selbst glauben die Weisheit mit Löffeln gefressen zu haben. Mann kann das ja auch schön als Schwanzverlängerung verwenden wenn man sonst irgendwelche Minderwertigkeitskomplexe hat. Und wehe es kommt einer daher der sich wagt Kritik an dem heiligen Werkzeug zu äussern... Ich bin jetzt raus hier. temp schrieb: > Wilhelm M. schrieb: >> Du debug-st einfach zuviel ;-) Verwende mehr compiletime-Konstrukte, >> Strong-Types, etc, u.s.w. und Deine "Debugging-Experience" wird sich >> massiv verändern. > > Wenn das alles ist was an Argumenten bleibt hat sich jede weitere > Diskussion erübrigt. Er macht nur, was vorher mit seinen zig anderen Argumenten dafür von der Gegenseite gemacht wurde. Ja, der Gegenstand der Diskussion hat Nachteile zu anderen, aber eben auch viele Vorteile, die diese Nachteile überwiegen könnte, um es wertfrei zu schreiben. Und weniger debuggen durch besser Typprüfung ist ein solcher "andere Nachteile überwiegender Vorteil". temp schrieb: > Und wehe es > kommt einer daher der sich wagt Kritik an dem heiligen Werkzeug zu > äussern... > Ich bin jetzt raus hier. Ja, dann, dann, dann ... dann entziehst Du Dich der Diskussion. Viel Spaß beim debuggen ;-) temp schrieb: ... > Beweis das mal. > Das ändert rein garnichts. Das Schieben mit Konstanten erfolgt doch > nicht zur Laufzeit. Das Berechnet der Compiler zur Laufzeit. Und am Ende Eher: Das Berechnet der Compiler zur Übersetzungszeit. Ihr macht ja schon Sublimationsfehler. Das ist dann, wenn das Gehirn als Dampf durch die Ohren austritt. Hitzige Diskussion, was? Dabei sind doch neue Features was sehr schönes. Besonders wenn niemand einen zwingt sie zu benutzen:P
Gast
#6546208
Jedzia D. schrieb: > temp schrieb: > ... >> Das Berechnet der Compiler zur Laufzeit. > Eher: Das Berechnet der Compiler zur Übersetzungszeit. Was das gleiche ist: Du hast den Satz vielleicht nicht aufmerksam gelesen. Und wenn män es klarer schreiben will: Das berechnet der Compiler. (Punkt) temp schrieb: > Und nein, always_inline ist leider nicht die Lösung und locale O3 > Optimierung auch nicht. Optimierung und always_inline haben Einfluß auf Optimierung, aber nicht auf die Erzeugung von Debug-Info. Was in die Richtung geht wäre Attribut "artificial", vielleicht hilft das ja? Antwort schreibenBitte melde dich an, um einen Beitrag zu schreiben. |
Anzeige
|