2016-10-11 2 views
2

Warum druckt der folgende Code 1, obwohl ich zwei Elemente in die Karte einfügen? Wie überprüft Std: Map, ob zwei Objekte gleich sind?

#include <iostream> 
#include <map> 
#include <string> 
#include <utility> 

struct Foo 
{ 
    Foo(int bar, const std::string& baz) 
    : bar(bar) 
    , baz(baz) 
    {} 

    int bar; 
    std::string baz; 

    bool operator<(const Foo& rhs) const 
    { 
    if (bar < rhs.bar && baz < rhs.baz) 
    { 
     return true; 
    } 
    else 
    { 
     return false; 
    } 
    } 
}; 

int main() 
{ 
    Foo first(0, "test"); 
    Foo second(1, "test"); 
    std::map<Foo, std::string> m; 
    m.insert(std::make_pair(first, "test")); 
    m.insert(std::make_pair(second, "test1")); 
    std::cout << m.size() << std::endl; 
} 

Der zweite Aufruf von insert() sagt, dass wir bereits das Element in der Karte. Warum?

Mein previous question wurde versehentlich wegen des Tippfehlers geschlossen. Ich weiß, dass insert Ihnen sagen wird, ob dieses Element bereits in dem Container ist.

+6

'Operator <' muss eine strenge schwache Ordnung definieren. Deines nicht. – Pubby

+0

@Pubby Was meinst du mit "streng schwacher Ordnung"? – FrozenHeart

+0

http://StackOverflow.com/Questions/979759/Operator-and-Strict-weak-Ordering – Pubby

Antwort

6

Die Karte insert() verwendet die operator<, die Sie angegeben haben, um die Äquivalenz zwischen Elementen zu bestimmen. Wenn a < b und b < a beide falsch sind, werden die beiden Elemente als gleich betrachtet.

Ihre operator<() ist inkonsistent, weil sie nicht die notwendigen strict weak ordering definiert. Betrachten Sie beispielsweise a.bar < b.bar und ; dann ist a < b falsch und b < a ist falsch, so glaubt die Karte a == b.

In Ihrem speziellen Fall, wenn first und second zu vergleichen, dann first.baz und second.baz sind beide "test", so beiden Vergleiche return false, und die Elemente werden als gleich betrachtet.

Sie brauchen so etwas wie:

bool operator<(const Foo& rhs) const 
{ 
    return std::tie(bar, baz) < std::tie(rhs.bar, rhs.baz); 
} 
+0

Kann ich einfach 'return bar ? – FrozenHeart

+4

@FrozenHeart: Nr. –

+1

@FrozenHeart Sie können tun, was Sie wollen, so kompliziert oder so einfach wie Sie es wünschen, aber wenn es nicht [strengen schwachen Bestellbeschränkungen] entspricht (https://en.wikipedia.org/ wiki/Weak_ordering # Strict_weak_orderings), es wird nicht funktionieren. Das tut es nicht. In Ihrem Fall 'return bar WhozCraig

Verwandte Themen