What is this use of std :: map?

Can someone explain the output I get from this simple program using std::map . Notice that I insert p into the map, but not q , but he says that he found both of them, but also says that there is only 1 element on the map!

 #include <map> #include <iostream> struct screenPoint { float x = 0, y = 0; screenPoint(float x_, float y_): x{x_}, y{y_}{} }; bool operator<(const screenPoint& left, const screenPoint& right){ return left.x<right.x&&left.y<right.y; } std::map<screenPoint, float> positions; int main(int argc, const char * argv[]) { auto p = screenPoint(1,2); auto q = screenPoint(2,1); positions.emplace(p,3); auto f = positions.find(p); auto g = positions.find(q); if (f == positions.end()){ std::cout << "f not found"; } else { std::cout << "f found"; } std::cout << std::endl; if (g == positions.end()){ std::cout << "g not found"; } else { std::cout << "g found"; } std::cout << std::endl; std::cout << "number elements: " << positions.size() << "\n"; return 0; } 

Output:

 f found g found number elements: 1 
+5
source share
2 answers

The problem is how you defined the comparison functor, in this case. The two elements p and q have the same x and y , just inverted. Your logic checks that x one less than x , and also y s. This can never be evaluated to true for these entries.

Try this snippet:

 int main() { auto p = screenPoint(1,2); auto q = screenPoint(2,1); std::cout << std::boolalpha << (p < q) << " " << (q < p) << std::endl; } 

He will print

 false false 

So p not less than q , and q not less than p . As for the card, this makes them equivalent.

+5
source

To use the data type in std::map , it must have a specific order called strict weak ordering ( https://en.wikipedia.org/wiki/Weak_ordering ). This means that the inequality operator ( < ) obeys a very specific set of rules. However, the operator you specified is not weak. In particular, given the two screenPoint s, a and b constructed from (1,2) and (2,1), respectively, you will see that this is a lie both a < b and b < a . In strict weak order, this will require a == b , which is wrong!

Since your inequality operator does not satisfy the requirement of strict weak ordering, map ends with unexpected things. I recommend reading more detailed information about what the order is and reading / thinking about why the card requires it. In the short term, you can override your statement as follows:

 bool operator<(const screenPoint& left, const screenPoint& right){ if (left.x != right.x) return left.x < right.x; else return (left.y < right.y); } 
+3
source

All Articles