Jerome Baldridge
Jerome Baldridge

Reputation: 528

Why is this std::map key not getting found?

I asked a similar question once before and now I have a related problem. Below, the output is "not found" and the number of elements printed is 2.

The line positions.emplace(r,q); clearly inserts the element and the map size is correct, so why is r not found? p is found (not logged in this example).

#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, screenPoint> positions;

int main(int argc, const char * argv[]) {

  auto p = screenPoint(593,271.5);
  auto q = screenPoint(595.5,269.5);
  auto r = screenPoint(599,267);
  positions.emplace(p,q);
  positions.emplace(r,q);

  auto f = positions.find(r);

  if (f == positions.end()){
    std::cout << "not found";
  } else {
    std::cout << "found";
  }

  std::cout << std::endl;

  std::cout << "number elements: " << positions.size() << "\n";
  return 0;
}

Upvotes: 2

Views: 136

Answers (2)

NathanOliver
NathanOliver

Reputation: 181057

Your comparison operator

bool operator<(const screenPoint& left, const screenPoint& right){
  return left.x<right.x||left.y<right.y;
}

Is incorrect. You need to use an if statement and if the x's are equal return if left.y is less than right.y otherwise return left.x < right.x. or use std::tie like

bool operator<(const screenPoint& left, const screenPoint& right){
  return std::tie(left.x, left.y) < std::tie(right.x, right.y);
}

Upvotes: 2

aschepler
aschepler

Reputation: 72473

Your operator< is not a Strict Weak Ordering. You have for example both p<q and q<p. This means Undefined Behavior for any map operations.

One way to provide a valid operator<, ignoring NaNs, would be:

bool operator<(const screenPoint& left, const screenPoint& right) {
    return left.x < right.x ||
           ( left.x == right.x && left.y < right.y );
}

Upvotes: 3

Related Questions