Verrücktes std::set::insert



  • #include <set>
    #include <iostream>
    
    struct MyPair
    {
        int a;
        int b;
    
        MyPair(int a = 0, int b = 0)
            : a{a}
            , b{b}
        {
        }
    
        friend constexpr bool operator<(MyPair const& lhs, MyPair const& rhs)
        {
            return lhs.a < rhs.a;
        }
    };
    
    int main()
    {
        std::set <MyPair> s;
        s.insert({2, 3});
    
        // Was gibt es hier aus?
        std::cout << s.size() << "\n";
    
        s.clear();
        s.insert(MyPair{2, 3});
        
        // und hier?
        std::cout << s.size() << "\n";
    }
    

    Sch*** Standard, dass std::set mit std::initializer_list überladen wird.
    Mit std::initializer_list überladen ist IMMER falsch.

    Was haltet ihr davon?



  • Wenn ich die default werte des Konstruktors entferne kommt bei beiden 1 raus.
    Ich sehe da kein Problem des standards.



  • Soll das ein Rätsel sein?



  • @firefly
    Im Beispiel sind die default dumm, aber nötig für das Beispiel. Mein Konstruktor ist aber überladen Mit jeweils einem oder 2 Params. Und ich habe nicht vor das zu ändern.

    @manni66
    In komplexerem Code ist das nicht offensichtlich, dass das passiert.

    So wie es ist, ist es unituitiv. Einfach ein schlechtes Klassen Interface. Es ist einfach falsch zu machen #Meyers.



  • Wenn du unbedingt das alte verhalten haben willst dann musst du den code als c++03/c++98 übersetzen lassen.
    Oder du verwendest die neuen features wodurch man eine kopie beim insert vermeiden kann.
    Denn bei deinem Beispiel-code wird in beiden fällen ein temporäres objekt erzeugt, welche dann in das set kopiert wird.

    Mit C++11 lässt sich die kopie vermeiden in dem man statt std::insert std::emplace verwendet:

    #include <set>
    #include <iostream>
    
    struct MyPair
    {
        int a;
        int b;
    
        MyPair(int a = 0, int b = 0)
            : a(a)
            , b(b)
        {
            std::cout<<"ctor"<<std::endl;
        }
        
        MyPair(const MyPair&)
        {
            std::cout<<"copy-ctor"<<std::endl;
        }
        
        MyPair(MyPair&&)
        {
            std::cout<<"move-ctor"<<std::endl;
        }
    
        friend constexpr bool operator<(MyPair const& lhs, MyPair const& rhs)
        {
            return lhs.a < rhs.a;
        }
    };
    
    int main()
    {
        std::set <MyPair> s;
        s.emplace(2, 3); // << Hier wird nur ein objekt implace im set erzeugt
    
        // Was gibt es hier aus?
        std::cout << s.size() << "\n";
    
        s.clear();
        s.emplace(MyPair{2, 3}); // << Hier wird immer noch kopiert
        
        // und hier?
        std::cout << s.size() << "\n";
    }
    


  • Ja ich bin eh schon auf emplace umgestiegen.

    Kann er aus dem insert(xvalue) nicht in einem Kontruktor ohne Seiteneffekte die konstruktion inplace machen?


Log in to reply