Operator Überladung - Automatisch generieren lassen?



  • Hey, ich stimme dir sogar zu, dass die Iostream Operatoren scheisse sind.
    Und trotzdem ist Operator Ueberladung gut so wie sie ist. Fehlen nur noch benutzerdefinierte Operatoren wie in Swift, das waere geil.



  • Kellerautomat schrieb:

    Hey, ich stimme dir sogar zu, dass die Iostream Operatoren scheisse sind.

    Erklär mal...



  • Ich finde Operatoren-Überladung in D ganz gut: http://dlang.org/operatoroverloading.html

    Irgendwo in der Mitte zwischen künstlerischer Freiheit und logischer Semantik.
    Zb. implementiert man die Operatoren <, <=, >, >= indem man eine einzige, strcmp-ähnliche Funktion implementiert - super. 👍

    Das schlimmste ist dass wenn C++-Operatoren sich anders als erwartet verhalten (warum kann ein Multiplikationsoperator nochmal eine Datenbankverbindung zurückgeben und eine Seite auf dem Drucker ausdrucken ?) man sie auch noch schwer findet - oder kapieren IDEs heutzutage bei der Verwendung eines Operators dass das ein überladener Operator ist und führen einen direkt zur Dekleration?

    ---

    Skym0sh0 schrieb:

    Kellerautomat schrieb:

    Ethon schrieb:

    Imho ein großer Fehler von C++ solch unsinnige Operatorenüberladungen zu erlauben. Erlaubt zwar Spielereien wie Boot.Spirit - aber ist sehr schlechter Stil.

    rofl

    Ja weil

    std::string s2;
    std::getline(std::cin, s2);
    
    std::string s1 = "Hallo";
    s1.append(" ");
    s1.append(s2);
    
    std::cout.write(s1).endl();
    

    auch so geil und viel kürzer ist.

    Oder hättest gerne sowas wie in Java, wo keine Operatorenüberladung exitiert, außer bei dem im Sprachkern festgenagelten java.lang.String (was ja wohl eine blöde Ausnahme darstellt)??

    Fände es so schöner:

    cout.writeln("Hallo ", cin.getln());
    


  • Skym0sh0 schrieb:

    Kellerautomat schrieb:

    Hey, ich stimme dir sogar zu, dass die Iostream Operatoren scheisse sind.

    Erklär mal...

    Noe.

    Ethon schrieb:

    Ich finde Operatoren-Überladung in D ganz gut: http://dlang.org/operatoroverloading.html

    Irgendwo in der Mitte zwischen künstlerischer Freiheit und logischer Semantik.
    Zb. implementiert man die Operatoren <, <=, >, >= indem man eine einzige, strcmp-ähnliche Funktion implementiert - super. 👍

    Das schlimmste ist dass wenn C++-Operatoren sich anders als erwartet verhalten (warum kann ein Multiplikationsoperator nochmal eine Datenbankverbindung zurückgeben und eine Seite auf dem Drucker ausdrucken ?) man sie auch noch schwer findet - oder kapieren IDEs heutzutage bei der Verwendung eines Operators dass das ein überladener Operator ist und führen einen direkt zur Dekleration?

    Naeh, die strcmp Semantik ist n grosser grosser Fehler. Macht alle Operatoren unnoetig langsam aufgrund Funktionalitaet die nicht gebraucht wird. Das passt in C++ schon so. Und in C++17 (oder schon 14 (?)) kriegen wir die sogar mit = default.

    Am schlimmsten ist opEquals als member. Hat man gar nichts von Java gelernt? Buh...

    Ethon schrieb:

    Fände es so schöner:

    cout.writeln("Hallo ", cin.getln());
    

    Naeh. Das sollten schon freie Funktionen sein, und dann sollte es natuerlich readln heissen wenn schon. Aber freie Funktionen mit Membersyntax aufrufen finde ich auch geil.



  • Kellerautomat schrieb:

    Naeh, die strcmp Semantik ist n grosser grosser Fehler. Macht alle Operatoren unnoetig langsam aufgrund Funktionalitaet die nicht gebraucht wird. Das passt in C++ schon so. Und in C++17 (oder schon 14 (?)) kriegen wir die sogar mit = default.

    Am schlimmsten ist opEquals als member. Hat man gar nichts von Java gelernt? Buh...

    Ich denke mal dass da recht viel optimiert werden kann da der Compiler ja ungefähr versteht was die Funktion macht.

    Dass opEquals eine Memberfunktion ist wird vermutlich darin begründet sein dass da unkomplizierter bei Klassen (die ja Referenztypen sind) und Polymorphie funktioniert.



  • Ethon schrieb:

    Ich denke mal dass da recht viel optimiert werden kann da der Compiler ja ungefähr versteht was die Funktion macht.

    Vielleicht. Vielleicht auch nicht.

    Ethon schrieb:

    Dass opEquals eine Memberfunktion ist wird vermutlich darin begründet sein dass da unkomplizierter bei Klassen (die ja Referenztypen sind) und Polymorphie funktioniert.

    Man will keine Objekte mit (potentiell) unterschiedlichem Typ vergleichen. Das macht mal gar keinen Sinn.



  • Kellerautomat schrieb:

    Ethon schrieb:

    Dass opEquals eine Memberfunktion ist wird vermutlich darin begründet sein dass da unkomplizierter bei Klassen (die ja Referenztypen sind) und Polymorphie funktioniert.

    Man will keine Objekte mit (potentiell) unterschiedlichem Typ vergleichen. Das macht mal gar keinen Sinn.

    Wie willst du sonst Objekte vergleichen auf die du nur Basisklassenzeiger hast?

    Ist nur bei der Klassen-Version so. Bei structs sieht es anders aus:

    struct S
    {
        // lhs should be mutable object
        bool opEquals(const S s) { ... }        // for r-values (e.g. temporaries)
        bool opEquals(ref const S s) { ... }    // for l-values (e.g. variables)
    
        // both hand side can be const object
        bool opEquals(const S s) const { ... }  // for r-values (e.g. temporaries)
    }
    

    (Da structs in D eben Werttypen sind und keine Semantiken von Referenztypen beachtet werden müssen)



  • Kellerautomat schrieb:

    Man will keine Objekte mit (potentiell) unterschiedlichem Typ vergleichen. Das macht mal gar keinen Sinn.

    Naja, int und double sind doch auch unterschiedliche Typen und vergleichbar? Oder bei einer BigInt Klasse macht es auch Sinn diese mit normalen ints zu vergleichen. Also das pauschal als unsinnig abzutun ist glaub ich auch nicht ganz richtig.

    Kellerautomat schrieb:

    Hey, ich stimme dir sogar zu, dass die Iostream Operatoren scheisse sind.

    Also das mit dem =default sollte auch nur für die Vergleichsoperatoren gelten.



  • Ethon schrieb:

    Wie willst du sonst Objekte vergleichen auf die du nur Basisklassenzeiger hast?

    Am besten gar nicht. Wozu brauchst du sowas? Hab ich noch nie nuetzich verwendet gesehen.
    Und falls doch, bau ich mir eben eine virtuelle Funktion selbst, die den normalen operator == aufruft.


  • Mod

    Kellerautomat schrieb:

    oder schon 14 (?)

    Wenn der Post vor einem Jahr geschrieben worden wäre hätte ich die Frage verstanden...

    manni66 schrieb:

    spoler schrieb:

    Da es sich um Templates handelt, werden die Operatoren für viel mehr Überladungen herangezogen, als du willst.

    Welche sind das?

    Da wo nicht zusätzliche Operatoren angeboten werden sollen, also bspw. != komplementär zu == , werden die rel_ops -Funktionstemplates trotzdem vom unqualified name lookup gefunden (weil man, um rel_ops verwenden zu können, ihn per using -Direktive in den globalen Namensraum ausleeren muss). Eigentlich sollte rel_ops über ADL und eine Basisklasse funktionieren, darauf ist aber leider niemand gekommen.

    Naja, int und double sind doch auch unterschiedliche Typen und vergleichbar?

    EDit: int wird dabei zu double konvertiert. Kellerautomat meinte wohl etwas anderes, denn für string und char const* gibt es einen speziellen Vergleichsoperator.



  • happystudent schrieb:

    Naja, int und double sind doch auch unterschiedliche Typen und vergleichbar? Oder bei einer BigInt Klasse macht es auch Sinn diese mit normalen ints zu vergleichen. Also das pauschal als unsinnig abzutun ist glaub ich auch nicht ganz richtig.

    Noe. int und double sind nicht direkt vergleichbar. int ist implizit in double konvertierbar.

    happystudent schrieb:

    Also das mit dem =default sollte auch nur für die Vergleichsoperatoren gelten.

    Tut's doch auch. Also ==/!= und die ganzen Ordnungs-Operatoren.



  • Kellerautomat schrieb:

    Ethon schrieb:

    Wie willst du sonst Objekte vergleichen auf die du nur Basisklassenzeiger hast?

    Am besten gar nicht. Wozu brauchst du sowas? Hab ich noch nie nuetzich verwendet gesehen.
    Und falls doch, bau ich mir eben eine virtuelle Funktion selbst, die den normalen operator == aufruft.

    Beispielsweise bei map/set.

    Du würdest dir also eine Fehlermeldung wünschen anstatt einen eventuellen Fallback auf eine Basisfunktion (Object.opEquals) die die Objekte auf Identität prüft?



  • happystudent schrieb:

    Naja, int und double sind doch auch unterschiedliche Typen und vergleichbar? Oder bei einer BigInt Klasse macht es auch Sinn diese mit normalen ints zu vergleichen. Also das pauschal als unsinnig abzutun ist glaub ich auch nicht ganz richtig.

    Da hast du recht. Innerhalb einer Klassenhierarchie polymorphe Vergleichsoperatoren anzubieten wollte ich jedoch auch noch nie. Und darum ging es ja eigentlich:

    Kellerautomat schrieb:

    Ethon schrieb:

    Dass opEquals eine Memberfunktion ist wird vermutlich darin begründet sein dass da unkomplizierter bei Klassen (die ja Referenztypen sind) und Polymorphie funktioniert.

    Man will keine Objekte mit (potentiell) unterschiedlichem Typ vergleichen. Das macht mal gar keinen Sinn.

    Ethon schrieb:

    Beispielsweise bei map/set.

    Du würdest dir also eine Fehlermeldung wünschen anstatt einen eventuellen Fallback auf eine Basisfunktion (Object.opEquals) die die Objekte auf Identität prüft?

    Polymorphe Typen in Maps / Sets? Sodass man ohnehin eine eigene Vergleichsfunktion braucht weil man nicht die Zeigerwerte der std::unique_ptr s vergleichen will? Und da du diese ja spät gebunden brauchst ist das Resultat also von Membern / Methoden abhängig, über die die Basisklasse nicht verfügt? Merkwürdige Ordnungsrelation.



  • Kellerautomat schrieb:

    Naeh, die strcmp Semantik ist n grosser grosser Fehler. Macht alle Operatoren unnoetig langsam aufgrund Funktionalitaet die nicht gebraucht wird. Das passt in C++ schon so. Und in C++17 (oder schon 14 (?)) kriegen wir die sogar mit = default.

    Warte mal, das ist wirklich ein Feature?
    Ich hab das einfach nur als nette Idee meinerseits gedacht.




Anmelden zum Antworten