Make an std::map with a coordinate as key

c++, stdmap, visual-c++

Solution

« std::map is a sorted associative container that contains key-value pairs with unique keys. Keys are sorted by using the comparison function Compare. » from cppreference

The default comparison function is `std::less` which will use the operator< on the `Key` objects.

Thus, the problem lies in the `operator<` of `Coordinate` :

bool operator<(const Coordinate& coord) const {
 if(x + y + z < coord.x + coord.y + coord.z)
    return true;
 return false;
}

`(1, 0, 0) < (0, 1, 0)` is false but `(0, 1, 0) < (1, 0, 0)` is also false, so as far as `std::map` is concerned, `(1, 0, 0) == (0, 1, 0)`.

In order to use `Coordinate` objects as keys in a `std::map`, you'll need to find the correct strict weak ordering criterion (the `operator<`) that meets your needs.

As other said, you could use something like `std::tie` (in C++11) which will first compare `x`, then `y` then `z` like this :

bool operator<(const Coordinate& coord) const {
    if(x < coord.x) return true;
    if(x > coord.x) return false;
    //x == coord.x
    if(y < coord.y) return true;
    if(y > coord.y) return false;
    //x == coord.x && y == coord.y
    if(z < coord.z) return true;
    if(z > coord.z) return false;
    //*this == coord
    return false;
}

Problem

It seems impossible to create an std::map with a coordinate as key. When (x+y+z) is the same for both coordinates, the map just overrides the previous one. Example: ``` map[Coordinate(1, 0, 0)] = object1; map[Coordinate(0, 1, 0)] = object2; map[Coordinate(0, 0, 1)] = object3; ``` This will result in there being a std::map with 1 element, which contains `object3` as value and `Coordinate(0, 0, 1)` as key. How can I prevent this so it'll contain all values? ``` #pragma once struct Coordinate { double x, y, z; Coordinate(double x, double y, double z) : x(x), y(y), z(z) {} bool operator<(const Coordinate& coord) const { if(x + y + z < coord.x + coord.y + coord.z) return true; return false; } bool operator==(const Coordinate& coord) const { if(x == coord.x && y == coord.y && z == coord.z) return true; return false; } inline bool isInRange(Coordinate coord, int range) const { if(pow(coord.x - this->x, 2) + pow(coord.y - this->y, 2) + pow(coord.z - this->z, 2) <= range*range) return true; return false; } }; ```

Original source

Related problems