Anzahl gleicher Elemente mit equal_range berechnen



  • Sone schrieb:

    Übrigens, wenn du den kleiner-als Operator überlädst, solltest du auch immer direkt den ist-gleich Operator mit überladen. Die kommen meistens im Zweierpack.

    Wozu? operator< reicht doch immer völlig.

    Dazu noch ein kleines Rätsel:

    std::cout << std::boolalpha << (x < y || y < x || x == y) << '\n';
    // Ausgabe: false
    

    x, y sind dabei von Typen aus reinem C++.



  • lazyprogger schrieb:

    Sone schrieb:

    Übrigens, wenn du den kleiner-als Operator überlädst, solltest du auch immer direkt den ist-gleich Operator mit überladen. Die kommen meistens im Zweierpack.

    Wozu? operator< reicht doch immer völlig.

    stl-algos verwenden eigentlich je nach dem, den op< oder den o==. und daraus werden sich die anderen vier gebaut. den op== aus dem op< zu bauen, kann lahm sein.
    deshalb sollte man die beiden anbieten.



  • lazyprogger schrieb:

    Dazu noch ein kleines Rätsel:

    std::cout << std::boolalpha << (x < y || y < x || x == y) << '\n';
    // Ausgabe: false
    

    x, y sind dabei von Typen aus reinem C++.

    double x=1;
        double y=log(-1);
    


  • volkard schrieb:

    stl-algos verwenden eigentlich je nach dem, den op< oder den o==. und daraus werden sich die anderen vier gebaut. den op== aus dem op< zu bauen, kann lahm sein.
    deshalb sollte man die beiden anbieten.

    Wenn ich sort will, dann schreibe ich op< und gut ist, für find mach ich op==. Und op== aus op< aufbauen gibt dem Compiler etwas zu tun, aber langsamer ist das schlussendlich nicht. Möglichst alle Operatoren für alle Eventualitäten zu überladen macht den Code auch nicht generischer.

    Dass die std-algos op== verwenden ist recht so, weil manchmal kann op< tatsächlich viel lahmer sein, aber das sind dann Spezialfälle.



  • ich sehe zu viele funktionen xD
    bin verwirrt 😃
    also was ist jetzt richtig?

    Die Qualifizierung mit dem Klassennamen (Element::) musst du weglassen, das muss eine unqualified-id sein.

    wieso geht das? bei anderen methoden muss ich ja das Element:: auch schreiben?



  • lazyprogger schrieb:

    Wenn ich sort will, dann schreibe ich op< und gut ist, für find mach ich op==. Und op== aus op< aufbauen gibt dem Compiler etwas zu tun, aber langsamer ist das schlussendlich nicht. Möglichst alle Operatoren für alle Eventualitäten zu überladen macht den Code auch nicht generischer.

    Es ist praktisch, wenn man die map einfach so mal durch eine unordered_map austauschen kann. oft genug baue ich aber auch klassen, die echt nur einen brauchen.

    lazyprogger schrieb:

    Dass die std-algos op== verwenden ist recht so, weil manchmal kann op< tatsächlich viel lahmer sein, aber das sind dann Spezialfälle.

    So speziell wie string.

    halt, ich meinte nicht, daß der op< lahmer als der op== ist (das ist schon selten), sondern dass a<b||b<a gerne mal lahmer ist als !(a==b).



  • ACnut schrieb:

    ich sehe zu viele funktionen xD
    bin verwirrt 😃
    also was ist jetzt richtig?

    Welche gefällt Dir denn am besten?



  • bool Element:: operator <(const Element& E)
    {
        Element& blabla=*this;
        return blabla.ngen < E.ngen;
    }
    

    der sieht schön aus 🙂



  • ACnut schrieb:

    bool Element:: operator <(const Element& E)
    {
        Element& blabla=*this;
        return blabla.ngen < E.ngen;
    }
    

    der sieht schön aus 🙂

    Bleiben die Fragen
    - wozu Du noch die Referenz blabla anlegst und
    - was Du noch besser machen koenntest, damit folgendes kompiliert:

    bool f(const Element& x, const Element& y){
      return x<y;
    }
    


  • volkard schrieb:

    Es ist praktisch, wenn man die map einfach so mal durch eine unordered_map austauschen kann.

    Eine Hashfunktion schreibt sich nicht "einfach so".



  • lazyprogger schrieb:

    volkard schrieb:

    Es ist praktisch, wenn man die map einfach so mal durch eine unordered_map austauschen kann.

    Eine Hashfunktion schreibt sich nicht "einfach so".

    Für einige Dinge sind Hashfunktionen bereits vorprogrammiert. Und wenn meine Klasse nur aus einigen Skalaren oder Strings besteht, ist es auch nicht so schwer.



  • Sone schrieb:

    Für einige Dinge sind Hashfunktionen bereits vorprogrammiert. Und wenn meine Klasse nur aus einigen Skalaren oder Strings besteht, ist es auch nicht so schwer.

    Es geht darum, dass der Wechsel von std::map zu std::unordered_map mit dem Vorhandensein des operator== nicht getan ist.

    Man muss in den meisten Fällen std::hash spezialisieren -- und falls nicht, ist ein operator== sehrwahrscheinlich auch schon vorhanden.



  • Furble Wurble schrieb:

    ACnut schrieb:

    bool Element:: operator <(const Element& E)
    {
        Element& blabla=*this;
        return blabla.ngen < E.ngen;
    }
    

    der sieht schön aus 🙂

    Bleiben die Fragen
    - wozu Du noch die Referenz blabla anlegst und
    - was Du noch besser machen koenntest, damit folgendes kompiliert:

    bool f(const Element& x, const Element& y){
      return x<y;
    }
    

    -damit ich keine kopie habe
    -wie tu ich das?



  • ACnut schrieb:

    Furble Wurble schrieb:

    ACnut schrieb:

    bool Element:: operator <(const Element& E)
    {
        Element& blabla=*this;
        return blabla.ngen < E.ngen;
    }
    

    der sieht schön aus 🙂

    Bleiben die Fragen
    - wozu Du noch die Referenz blabla anlegst und
    - was Du noch besser machen koenntest, damit folgendes kompiliert:

    bool f(const Element& x, const Element& y){
      return x<y;
    }
    

    -damit ich keine kopie habe
    -wie tu ich das?

    Du hast doch auch keine Kopie, wenn Du das Member direkt benutzt.

    Und zu zweitens: das sollte keine Geheimniskrämerei sein. Ich hätte noch das Stichwort const-correctness hinzufügen sollen.
    Dein Member operator<() ist keine const-Methode, kann daher auch nicht auf Element Objekten aufgerufen werden, die const sind.
    Eigentlich sollte das allerdings funktionieren, da der operator<() das Objekt auf dem er aufgerufen wird ja wirklich nur schreibend anfasst. Gelöst wird das durch Dich, indem Du den operator<() als const-member-Funktion deklarierst:

    struct Element
    {
      int numgen;
      int index;
      bool operator<(const Element&) const;
    };
    
    bool operator<(const Element& x) const {
      return numgen < x.numgen;
    }
    

    Das solltest Du Dir für alle Member angewöhnen, die "Ihr"-Objekt nicht verändern.

    Aber es wurde ja auch schon gezeigt, dass Du den operator<() lieber als freie Funktion implementierst:

    bool operator<(const Element&, const Element&);
    


  • hmmm, hört sich verständlich an 🙂

    vielen dank für eure hilfe


Anmelden zum Antworten