Erst C oder gleich C++ ???



  • Shade Of Mine schrieb:

    wenn raii bei dir unter gc fällt...
    dann hat c++ ja einen gc und der artikel ist immernoch falsch.

    Nö. Er sagt ja nicht, daß es unmöglich wäre. Aber um effizient Daten an Closures weiterzugeben, muß man Smart-Pointer (oder natürlich den neuesten Versuch, den ursprünglichen Designfehler erträglicher zu machen, nämlich die Move-Semantik) bemühen, also einen mehr oder weniger manuellen GC-Mechanismus. In einer Umgebung mit GC gehts einfach so.

    Shade Of Mine schrieb:

    Was auch immer. Das komplette "Jedes struct ist jetzt eine Klasse" inklusive aller Implikationen, eine davon z.B. Default-, Kopierkonstruktor und Zuweisungsoperator für alle Klassen, ist ein gewaltiger Designfehler - IMHO.

    begründung?
    weil value semantik schlecht ist?

    Barry Kelly schrieb:

    Thing is, writing correct value types is far harder than writing correct Java-style types, and C++ has some features that seem to make value types the default.
    ...
    But when did common domain objects like Person, Car and Account ever need to act like integers, freely copyable and duplicated hither and thither?

    Shade Of Mine schrieb:

    ergo ist value semantik essentiell.
    schau dir java an: du tust dauernd clone aufrufen und was ist das erste was man einem java programmierer beibringt? finger weg von clone. weils ein käse ist.

    ja, reine referenz semantik ist wahnsinnig toll.

    Für die spreche weder ich noch er. Aber eine saubere Trennung wäre einiges wert gewesen.

    Shade Of Mine schrieb:

    was hat source code mit ABI zu tun?

    Um delete so abzuändern, daß es auch Arrays freigeben müßte, hätte die Metainformation, die new vor dem Speicherblock unterbringt, erweitert werden müssen => ABI-Inkompatibilität. Beim Linken älterer Module kann das relevant sein. (Allerdings bin ich nicht der Auffassung, daß das ein Hinderungsgrund hätte sein müssen.)

    Shade Of Mine schrieb:

    und du kannst new effizienter implementieren als new[] - ist einfach so.

    Ist ja okay - dagegen hat ja niemand etwas. Aber was spricht gegen das hier:

    template <typename T>
        void pseudoHighLevelDelete (T* data)
    {
        if (!data)
            return;
        if (((unsigned*) data)[-1] == 0) // etwa drei ASM-Instruktionen mehr
            data->~T ();
        else
            for (unsigned i = ((unsigned*) data)[-1]; i > 0; --i)
                (data++)->~T ();
        std::free (data);
    }
    

    ?

    asc schrieb:

    Ich habe nie C gelernt

    Dann wirds ja höchste Zeit.

    Edit, @Shade: Obige Fragen, warum man throw 1; braucht und inwiefern etwas, das so unausgegoren ist wie std::type_info, nicht unter deine Auffassung von "undurchdacht" fällt, wären auch noch offen. Und bis jetzt habe ich auch noch kein gutes Argument gehört, warum std::type_info::name() nicht einfach aufgeteilt wurde in eine Mangled-Variante (compilerspezifisch, aber maximale Effizienz) und eine standardisierte Demangled-Variante. Und auch, wozu man auf Gleitkommatypen basierende Enumerationen braucht, weiß ich noch nicht.

    Alternativ kannst du mir aber gerne drei Aspekte von C++ nennen, die ich nicht verstanden habe. 🤡



  • audacia schrieb:

    Nö. Er sagt ja nicht, daß es unmöglich wäre. Aber um effizient Daten an Closures weiterzugeben, muß man Smart-Pointer (oder natürlich den neuesten Versuch, den ursprünglichen Designfehler erträglicher zu machen, nämlich die Move-Semantik) bemühen, also einen mehr oder weniger manuellen GC-Mechanismus. In einer Umgebung mit GC gehts einfach so.

    boost lambda kommt zB ohne allokationen aus...

    move semantik kannst du auch jetzt schon mit mojo haben 😉

    warum genau ist value semantik aber ein design fehler?
    bedenke: value semantik kann referenz semantik simulieren - umgekehrt geht es nicht.

    Thing is, writing correct value types is far harder than writing correct Java-style types, and C++ has some features that seem to make value types the default.
    ...
    But when did common domain objects like Person, Car and Account ever need to act like integers, freely copyable and duplicated hither and thither?

    Irrelevant.

    Natürlich gibt es pitfalls bei bei value typen - aber auch referenz typen sind nicht pitfall-los. zB hast du enorm viele java klassen die interne handles hergeben.

    Shade Of Mine schrieb:

    ergo ist value semantik essentiell.
    schau dir java an: du tust dauernd clone aufrufen und was ist das erste was man einem java programmierer beibringt? finger weg von clone. weils ein käse ist.

    ja, reine referenz semantik ist wahnsinnig toll.

    Für die spreche weder ich noch er. Aber eine saubere Trennung wäre einiges wert gewesen.

    Besser geht immer, aber warum ist value semantik schlecht?
    mächtige features sind oft mit pitfalls verbunden...

    deshalb sind sie aber doch nicht schlecht.
    schau dir C# an - dort wird value und reference semantik getrennt - ist auch nicht wirklich perfekt.

    aber es geht auch nicht um perfektion sondern darum ob es funktioniert. und c++ funktioniert.

    Shade Of Mine schrieb:

    Um delete so abzuändern, daß es auch Arrays freigeben müßte, hätte die Metainformation, die new vor dem Speicherblock unterbringt, erweitert werden müssen => ABI-Inkompatibilität. Beim Linken älterer Module kann das relevant sein. (Allerdings bin ich nicht der Auffassung, daß das ein Hinderungsgrund hätte sein müssen.)

    ich finde die trennung nicht störend und es bringt wie du gesagt hast ja auch performance.
    also wo genau ist das problem?

    anders geht immer. aber damit wird kein problem gelöst, denn new/new[] ist kein problem.

    der new operator ruft übrigens den operator new auf - der new operator muss somit _kein_ bookkeeping machen, während der new[] operator sehr wohl eins machen muss.

    da ich die new operatoren aber selber definieren kann, ist es schwer hier zu optimieren ohne 100 sonderfälle zu betrachten.

    das ganze ist zB dann relevant, wenn du fixed size allokationen hast - dann hast du 0 bookkeeping und nur der new[] operator muss bookkeeping machen.



  • audacia schrieb:

    Edit, @Shade: Obige Fragen, warum man throw 1; braucht

    Warum sollte es verboten werden?

    ich mag nunmal auch einen zeiger werfen können (siehe MFC) und das macht manchmal ja auch sinn. und wenn ich zeiger werfen darf, dann wird es plötzlich sehr komisch wenn ich restrikte was für zeiger ich werfen darf.

    ich sehe keinen sinn einer restriktion. welchen vorteil habe ich, wenn ich verbiete zeiger zu werfen?

    das so unausgegoren ist wie std::type_info, nicht unter deine Auffassung von "undurchdacht" fällt, wären auch noch offen.

    weil es so funktioniert wie es gedacht ist.
    es könnte besser sein, aber ja, so ziemlich alles könnte besser sein.

    name() funktioniert: du kannst es verwenden um eine readable form des typs zu bekommen - die genaue form ist ID. wenn deine implementation es schlecht definiert, jo mei.

    Alternativ kannst du mir aber gerne drei Aspekte von C++ nennen, die ich nicht verstanden habe. 🤡

    exceptions, value semantik und new



  • Erst C oder gleich C++ ???

    Back to topic:

    1. Ja, erst C lernen.
    2. Und auch bei C bleiben.


  • troll



  • Shade Of Mine schrieb:

    audacia schrieb:

    Nö. Er sagt ja nicht, daß es unmöglich wäre. Aber um effizient Daten an Closures weiterzugeben, muß man Smart-Pointer (oder natürlich den neuesten Versuch, den ursprünglichen Designfehler erträglicher zu machen, nämlich die Move-Semantik) bemühen, also einen mehr oder weniger manuellen GC-Mechanismus. In einer Umgebung mit GC gehts einfach so.

    boost lambda kommt zB ohne allokationen aus...

    Baut man mit boost lambda etwa Closures? Wie sieht das aus? Wo wird die Umgebung gespeichert?



  • Bashar schrieb:

    Baut man mit boost lambda etwa Closures? Wie sieht das aus? Wo wird die Umgebung gespeichert?

    kann man machen, ja.

    A language implementation cannot easily support full closures if its run-time memory model allocates all local variables on a linear stack. In such languages, a function's local variables are deallocated when the function returns. However, a closure requires that the free variables it references survive the enclosing function's execution. Therefore those variables must be allocated so that they persist until no longer needed. This explains why typically languages that natively support closures also use garbage collection. The alternative is for the language to accept that certain use cases will lead to undefined behaviour, as in the proposal for lambda expressions in C++.



  • topic --> out off topic --> out out off topic ... => in future meinungsverschiedenheiten zwischen programmierer

    greetz!



  • Shade Of Mine schrieb:

    ich sehe keinen sinn einer restriktion. welchen vorteil habe ich, wenn ich verbiete zeiger zu werfen?

    Einheitlichen Exception-Typen, unproblematischeres Dispatching. Überhaupt Einheitlichkeit. Ein gewisser Zwang dahingehend, Exceptions mit sinnvollen Fehlermeldungen zu werfen (weil die leichteste Variante, eine Exception zu werfen, dann nicht mehr throw 1; , sondern throw std::runtime_error ("array index out of bounds"); ist). Und weniger Typinformation für Basistypen in der Executable, deutlich geringeren Aufwand auf der RTL-Seite.

    Um deine Frage erneut gegen dich selbst zu wenden: wozu braucht man throw 1; ?

    Shade Of Mine schrieb:

    aber es geht auch nicht um perfektion sondern darum ob es funktioniert. und c++ funktioniert.

    Achso, sobald wir also über ein paar konkrete ("undurchdachte") Schwachstellen reden, gehts nur noch darum, daß es funktioniert 🤡
    Machst du es dir nicht ein bißchen einfach?

    Shade Of Mine schrieb:

    wenn deine implementation es schlecht definiert, jo mei.

    ?

    Shade Of Mine schrieb:

    exceptions, value semantik und new

    Nicht auch std::type_info?

    Shade Of Mine schrieb:

    Wikipedia schrieb:

    A language implementation cannot easily support full closures if its run-time memory model allocates all local variables on a linear stack. In such languages, a function's local variables are deallocated when the function returns. However, a closure requires that the free variables it references survive the enclosing function's execution. Therefore those variables must be allocated so that they persist until no longer needed. This explains why typically languages that natively support closures also use garbage collection. The alternative is for the language to accept that certain use cases will lead to undefined behaviour, as in the proposal for lambda expressions in C++.

    Interessanterweise ist genau das der Hintergrund meiner (und Barrys) Argumentation. Irgendwie willst du es nur nicht verstehen. Denn der Artikel ist ja Käse.



  • ~fricky schrieb:

    asc schrieb:

    [
    Ich habe nie C gelernt, bin nur durch einige Chaosprojekte auf C gestossen.

    soso, C code ist also per default chaotische, ne?

    Nein, aber wenn du es so lesen willst ist das dein Bier.

    C, wenn es einheitlich und in dessen Sprachparadigmen geschrieben ist, ist nicht chaotisch. C++ aber das bunt zwischen Sprachen (C und C++) und deren Paradigmen hin und her mischt, ist dies aber. Am schönsten sind noch Sachen wie Mischen von malloc/delete oder new/free, oder free grundsätzlich auf alle Arrays...

    Ich habe nichts gegen C, ich habe aber etwas gegen:
    a) C-Programmierer die nur über C++ meckern (Ich verlange nicht das man C++ mag, ich bin nur gegen das generelle C++ ist Sch****...). Ich hasse persönlich beispielsweise VB, dennoch akzeptiere ich das es VB gibt, und das es auch Gründe für VB gibt. Ich werde VB niemals mögen, das war es schon. Jede Sprache hat ihre Vorteile und Macken (sei es C, C++, Java, C#...) und jede Sprache (außer vielleicht sowas wie Brainfuck) hat ihr Sinn und ihre Einsatzgebiete.

    b) Programmierer die sich C++ Programmierer nenne, die aber teilweise widersprüchliche Sprachparadigmen mischen und eher schlechtes C mit ein wenig Ausnutzen der C++ Syntax. Ja, ich schimpfe auf C-Konzepte - aber vorwiegend im C++ Kontext.

    ~fricky schrieb:

    dabei hab' ich gestern erst irgendwo gelesen, dass sich der C++ user nicht für die C-wurzeln seiner lieblingssprache schämen sollte.
    🙂

    Mal ganz davon abgesehen das C++ nicht meine Lieblingssprache ist, schäme ich mich nicht dafür das C++ von C abstammt. Ich habe nur etwas dagegen wenn man meint das weil C++ seine Wurzeln in C hat, auch 30 Jahre nach Entstehung, C++ nur ein Sprachaufsatz auf C wäre. C++ hat eigene Paradigmen angenommen. C++ wird anders als C programmiert.

    Ich sehe C++ auch - in größeren Projekten - als wartbarer als C an (Teilweise durch OO und generische Programmierung). Dazu muss man aber auch sagen, das die kleinsten Projekte an denen ich bislang gearbeitet habe in der Größenordnung von etwa 100k+ Codezeilen liegen (Ich glaube das größte waren etwa 10 Mio Codezeilen). Zudem glaube ich das man C++ - wenn man es auf die C++ Art lernt - nicht schwerer zu lernen ist als eine Sprache wie C. Man braucht zwar länger um alle Bereiche zu lernen, aber manches benötigt man auch einfach anfangs nicht, oder nur soweit das man es verwenden, nicht aber Programmieren können muss.

    cu André



  • u_ser-l schrieb:

    asc schrieb:

    Ich habe nie C gelernt,

    doch, hast Du. Und zwar implizit durch Mitlernen im Rahmen von C++

    Wenn man von C++ alles herausnimmt, was von C stammt, kann man nicht einmal

    int main(){; }
    

    Nach der Definition lernt auch jeder Java und C# Entwickler C.

    Und wieder: Ich habe nie C gelernt. Den auch wenn ich C++ Syntaxelemente gelernt habe die in C ihren Ursprung haben, kann ich kein C programmieren. Und der C# Entwickler wird ebenso for, while, int... lernen und kann ebenso kein C-Programmieren. Einige Sprachelemente mögen gleich sein, dennoch kann man damit nicht C programmieren. Für die Programmieren müsste man auch - zumindest maginale - Kenntnisse der Bibliotheken haben. Ich bekomme auf Anhieb noch nicht einmal die Syntax von malloc, free, prinft hin.

    u_ser-l schrieb:

    ...und Zeiger durch Referenzen ersetzt...

    Zeiger sind ebenso Sprachbestandteil von C wie auch C++. Damit ist C++ aber noch immer kein C (auch wenn einige meinen das sie mit C-Code und der C-Programmierweise automatisch C++ Programmierer sind, wenn sie einen C++ Compiler verwenden).

    cu André



  • audacia schrieb:

    Einheitlichen Exception-Typen, unproblematischeres Dispatching. Überhaupt Einheitlichkeit. Ein gewisser Zwang dahingehend, Exceptions mit sinnvollen Fehlermeldungen zu werfen (weil die leichteste Variante, eine Exception zu werfen, dann nicht mehr throw 1; , sondern throw std::runtime_error ("array index out of bounds"); ist). Und weniger Typinformation für Basistypen in der Executable, deutlich geringeren Aufwand auf der RTL-Seite.

    Beantworte einfach die Frage und erzähl keine Marketingmärchen:
    Warum darf ich nicht objekt und zeiger werfen sondern nur eins von beiden.
    auf grund der value semantik muss man dann wohl objekte by value werfen, was aber n bisschen blöd ist wenn man exception chaining machen will.

    oder darf ich zeiger werfen und objekte?

    restriktionen, restriktionen,....
    und das mit weniger typinformationen kapiere ich nicht.

    du weisst wie exceptions implementiert sind, oder?

    Um deine Frage erneut gegen dich selbst zu wenden: wozu braucht man throw 1; ?

    langweilig, hab ich schon beantwortet: nämlich indem ich eine verwendung für T* gezeigt habe.

    Shade Of Mine schrieb:

    aber es geht auch nicht um perfektion sondern darum ob es funktioniert. und c++ funktioniert.

    Achso, sobald wir also über ein paar konkrete ("undurchdachte") Schwachstellen reden, gehts nur noch darum, daß es funktioniert 🤡
    Machst du es dir nicht ein bißchen einfach?

    Perfekte Features existieren nicht. name() kann man verwenden und es funktioniert. die form von name() ist auch standardisiert, nämlich als ID was aus sicht eines reflection system sehr viel sinn macht.

    dass ein reflection system nun name() eine passende form geben kann ist dabei recht praktisch. im c++ standard kann man hier nicht viel sinnvoll definieren. da ist jede definition gleich gut - schränkt aber reflection systeme uU ein.

    deshalb ist es besser nicht einzuschränken und die form von name() als ID zu definieren.

    Shade Of Mine schrieb:

    wenn deine implementation es schlecht definiert, jo mei.

    ?

    und deshalb wird die diskussion langweilig...
    ID heisst, dass deine implementierung name() frei definieren kann. wenn deine implementierung dies eben so tut dass es dir nicht passt, dann lebe damit oder nimm eine andere. die idee ist, sobald jemand eine sinnvolle verwendung für name() gefunden hat, können die compiler es implementieren und es gibt keine limitierungen.

    aktuell bringt dir aber eine standardisierte name() variante nichts, ausser dass es nett aussieht. also wozu limitieren was erlaubt ist?

    uU ist es sinnvoll per compiler switch zB name() als den name mangled namen zu definieren oder als ein pretty print, etc.

    Shade Of Mine schrieb:

    exceptions, value semantik und new

    Nicht auch std::type_info?

    nein, weil du type_info schon verstanden hast, nur du willst dass es mehr macht. das ist legitim. ich will ja auch dass java first class functions hat. aber das ist jetzt nicht wirklich etwas undurchdachtes in java.

    Interessanterweise ist genau das der Hintergrund meiner (und Barrys) Argumentation. Irgendwie willst du es nur nicht verstehen. Denn der Artikel ist ja Käse.

    ich verstehe nicht wo das problem liegt.
    du kannst problemlos mit shared_ptr arbeiten.
    du kannst problemlos _kopien_ ziehen. und du kannst problemlos referenzen ziehen.

    das sind features die du bei den meisten closure implementierungen nicht hast.

    ergo: wieder mehr features auf der value semantik seite.



  • Shade Of Mine schrieb:

    oder darf ich zeiger werfen und objekte?

    Nur Objekte. Du darfst sie auch kopieren.

    Shade Of Mine schrieb:

    du weisst wie exceptions implementiert sind, oder?

    Davon kannst du ausgehen.

    Shade Of Mine schrieb:

    langweilig, hab ich schon beantwortet: nämlich indem ich eine verwendung für T* gezeigt habe.

    Achso, weil das in MFC üblich ist, soll das erlaubt sein?

    Shade Of Mine schrieb:

    deshalb ist es besser nicht einzuschränken und die form von name() als ID zu definieren.

    Könnte ich zustimmen, wenn wir über std::type_info::mangled_name() redeten.
    Hier ist es tatsächlich so, wie du sagst: daß ich mir vor allem ein Feature mehr wünsche.

    Shade Of Mine schrieb:

    aktuell bringt dir aber eine standardisierte name() variante nichts, ausser dass es nett aussieht. also wozu limitieren was erlaubt ist?

    Ich kann mir da ein paar nette Anwendungsfälle für z.B. Serialisierung vorstellen.

    Shade Of Mine schrieb:

    ergo: wieder mehr features auf der value semantik seite.

    Ja, _noch_ mehr Features. Mit C++ ist tatsächlich fast alles umsetzbar.
    Ob man das aber zur Maxime erklären sollte, finde ich fraglich.



  • audacia schrieb:

    Shade Of Mine schrieb:

    oder darf ich zeiger werfen und objekte?

    Nur Objekte. Du darfst sie auch kopieren.

    Und damit ist exception chaining nicht mehr möglich.
    sehr clever.

    Shade Of Mine schrieb:

    langweilig, hab ich schon beantwortet: nämlich indem ich eine verwendung für T* gezeigt habe.

    Achso, weil das in MFC üblich ist, soll das erlaubt sein?

    Weil du viele techniken nicht umsetzen kannst wenn du keine exceptions als zeiger werfen kannst.

    das problem dabei ist, dass shared_ptr hier nämlich nicht hilft.

    man müsste einen umständlichen weg über pimpl gehen.

    und für was?

    Shade Of Mine schrieb:

    aktuell bringt dir aber eine standardisierte name() variante nichts, ausser dass es nett aussieht. also wozu limitieren was erlaubt ist?

    Ich kann mir da ein paar nette Anwendungsfälle für z.B. Serialisierung vorstellen.

    und das klappt super mit einer bestimmten implementierung.

    Shade Of Mine schrieb:

    ergo: wieder mehr features auf der value semantik seite.

    Ja, _noch_ mehr Features. Mit C++ ist tatsächlich fast alles umsetzbar.
    Ob man das aber zur Maxime erklären sollte, finde ich fraglich.

    Natürlich soll nicht jede Sprache alles können - aber value semantik ist etwas wichtiges: es muss sprachen mit value semantik geben.

    nicht jede sprache soll value semantik haben. referenz semantik macht auch sinn. es erleichtert viele sachen (schränkt dafür halt auch etwas ein) aber solche trade-offs sind wichtig. weil nicht immer will ich rohe power haben, sondern einfachere systeme wo ich bestimmte probleme einfacher lösen kann.



  • asc schrieb:

    Nach der Definition lernt auch jeder Java und C# Entwickler C.

    wußte gar nicht, daß java und C# Zeigerarithmetik haben.

    Aber egal.

    Ein C++ Programmierer, der kein C kann, kann kein C++, sondern nur eine Teilsprache von C++.

    Weil nämlich:

    <sprechplatte play>
    C++ ist eine Spracherweiterung von C.
    <sprechplatte stop>
    

    Jetzt haben wir es aber alle verstanden. ciao.

    Grüße



  • Shade Of Mine schrieb:

    Und damit ist exception chaining nicht mehr möglich.

    Interessanterweise implementiere ich in der Unit, die ich in obigem Artikel bespreche, Exception-Chaining für gewöhnliche C++-Exceptions (std::exception-Derivate). Ohne manuelle Kopien und mit gewöhnlichen auf dem Stack angelegten Objekten. Und wenn man ein paar sinnvolle Regelungen zur Destruktionsreihenfolge bei Chained Exceptions eingeführt hätte (kann sogar sein, daß es die gibt, aber das müßte ich nachlesen), wäre das auch mit der Beschränkung auf stackallozierte std::exception-Derivate problemlos in Standard-C++ machbar.

    Außerdem ist doch gerade Exception-Chaining ein Argument für einheitliche Exceptions. Du kannst jede innere Exception wrappen, ohne ihren Typen zu kennen. Da du sie auf das polymorphe std::exception& reduzieren kannst, ist es den Handlern der äußeren Exception möglich, spezielle innere Exceptions, von denen deine äußere Exceptions gar nichts weiß, mittels Polymorphie zuzugreifen und auszuwerten.

    Shade Of Mine schrieb:

    und das klappt super mit einer bestimmten implementierung.

    Jap. Und wenn es dann noch ein standardisiertes std::type_info::[pretty_]name() gäbe, könnte ich meine mit C++Builder unter Windows serialisierten Objekte mit GCC unter Linux weiterverwenden. Ein veritabler Mehrwert.
    (Allerdings hast du, wie ich bereits sagte, recht darin, daß das nicht undurchdacht ist. Es wäre nur eher ein äußerst sinnvolles zusätzliches Zusatzfeature gewesen. Aber das war ja auch nicht mein Kernpunkt bzgl. std::type_info.)

    Shade Of Mine schrieb:

    Natürlich soll nicht jede Sprache alles können - aber value semantik ist etwas wichtiges: es muss sprachen mit value semantik geben.

    Auch da stimme ich zu. Aber oben erwähntes Designproblem halte ich genauso für unpragmatisch radikal wie "alles ist ein Objekt".

    Man hätte auch in C++, ohne die heutigen Möglichkeiten einzuschränken, durchaus sauber zwischen Werte- und Referenzsemantik trennen können. Daß es nicht so kam, hängt aber vornehmlich mit der evolutionären Entstehung der Sprache zusammen ("C mit Klassen"), daher listete ich das auch nicht unter "undurchdacht".



  • u_ser-l schrieb:

    asc schrieb:

    Nach der Definition lernt auch jeder Java und C# Entwickler C.

    wußte gar nicht, daß java und C# Zeigerarithmetik haben.

    Aha, also sobald Zeiger in einer Sprache sind, ist es C? Sehr interessante Theorie.



  • gähn.

    Wenn es C enthält, enthält es auch Zeigerarithmetik.

    Enthält es keine Zeigerarithmetik, enthält es auch nicht C.

    Das ist übrigens keine "Theorie", sondern banale Tautologie (hä? Banana was ? 😮 )



  • audacia schrieb:

    Shade Of Mine schrieb:

    Und damit ist exception chaining nicht mehr möglich.

    Interessanterweise implementiere ich in der Unit, die ich in obigem Artikel bespreche, Exception-Chaining für gewöhnliche C++-Exceptions (std::exception-Derivate).

    Ich vermute ueber eine art pimpl? habe ich aber bereits erwaehnt dass das moeglich ist.

    aber ich sehe immernoch keinen grund warum es ein design fehler ist, dass ich alles werfen darf.

    ein vorteil ist, dass ich exception chaining haben kann ohne wrapper zu brauchen. oder aber ich werfe exception ohne allokationen zu haben - da ich eine exception pre-allocaten kann und dann werfe wenn ich muss.

    massig moeglichkeiten.

    Außerdem ist doch gerade Exception-Chaining ein Argument für einheitliche Exceptions. Du kannst jede innere Exception wrappen, ohne ihren Typen zu kennen. Da du sie auf das polymorphe std::exception& reduzieren kannst, ist es den Handlern der äußeren Exception möglich, spezielle innere Exceptions, von denen deine äußere Exceptions gar nichts weiß, mittels Polymorphie zuzugreifen und auszuwerten.

    kann ich problemlos haben wenn ich will.

    Man hätte auch in C++, ohne die heutigen Möglichkeiten einzuschränken, durchaus sauber zwischen Werte- und Referenzsemantik trennen können. Daß es nicht so kam, hängt aber vornehmlich mit der evolutionären Entstehung der Sprache zusammen ("C mit Klassen"), daher listete ich das auch nicht unter "undurchdacht".

    genauso wie java, dass keine value semantik anbietet?
    ich meine, es gibt ja nichtmal call by reference...

    ist das auch undurchdacht?



  • Shade Of Mine schrieb:

    Ich vermute ueber eine art pimpl? habe ich aber bereits erwaehnt dass das moeglich ist.

    Ja, aber wenn es nur von std::exception abgeleitete Exceptions gäbe, wäre das nicht nötig gewesen:

    typedef std::exception* PCppException; // mittels $HPPEMIT
    
    class PASCALIMPLEMENTATION ECppException : public Sysutils::Exception
    {
    private:
    	System::AnsiString FTypeName;
    	PCppException *FException; // zeigt auf die statisch, also z.B. auf dem
    	                           // Stack allozierte innere Exception,
    	                           // die dann vom entsprechenden Handler
    	                           // destruiert würde
    	__fastcall ECppException(char * _TypeName, void * ExcDesc)/* overload */;
    	...
    
    public:
    	__property PCppException StdException = {read=FCppException};
    	...
    };
    

    Sofern oben erwähnte Regeln existierten, wäre das dann auch in Standard-C++ machbar. Zeig mir mal, wie du das machst unter Berücksichtigung der gegenwärtigen "Zusatzfeatures", die ich für eine Beschränkung halte.

    Shade Of Mine schrieb:

    aber ich sehe immernoch keinen grund warum es ein design fehler ist, dass ich alles werfen darf.

    Es fällt einfach unter dein "wozu braucht man das" und behindert o.g. Mechanismen.

    Shade Of Mine schrieb:

    ein vorteil ist, dass ich exception chaining haben kann ohne wrapper zu brauchen.

    Wie das?

    Shade Of Mine schrieb:

    oder aber ich werfe exception ohne allokationen zu haben - da ich eine exception pre-allocaten kann und dann werfe wenn ich muss.

    Das geht genauso mit std::exception-Typen.

    Shade Of Mine schrieb:

    kann ich problemlos haben wenn ich will.

    Dann zeig mal her. Das glaube ich nämlich nicht.

    Shade Of Mine schrieb:

    genauso wie java, dass keine value semantik anbietet?
    ich meine, es gibt ja nichtmal call by reference...

    ist das auch undurchdacht?

    Lies genauer. Ich sagte ja, daß es nicht undurchdacht, sondern eine evolutionäre Fehlbildung ist.

    Bei Java wird das nicht undurchdacht, sondern gewollt gewesen sein. Aber ich weiß nicht, weshalb du andauernd den Vergleich mit Java forcierst. Sieh dir doch mal z.B. in Delphi die Trennung von Records (für die es z.B. Operatorenüberladungen gibt) und Klassen (die immer polymorph sind und sämtlich von TObject ableiten) an. In .NET ist das IIRC ähnlich. Das hätte man für C++ noch ein wenig ausbauen können, hätte dann mit structs die Wertesemantik wie heute, in Klassen aber z.B. standardmäßig keinen Kopierkonstruktor, standardmäßig Heap-Allokation, immer eine VTable etc.


Anmelden zum Antworten