创建一个坐标为键的std :: map

Jer*_*oen 7 c++ stdmap visual-c++

用坐标作为键创建一个std :: map似乎是不可能的.当两个坐标的(x + y + z)相同时,地图只会覆盖前一个坐标.例:

map[Coordinate(1, 0, 0)] = object1;
map[Coordinate(0, 1, 0)] = object2;
map[Coordinate(0, 0, 1)] = object3;
Run Code Online (Sandbox Code Playgroud)

这将导致有一个带有1个元素的std :: map,其中包含object3value和Coordinate(0, 0, 1)key.如何防止这种情况,它会包含所有值?

#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;
    }
};
Run Code Online (Sandbox Code Playgroud)

zak*_*ter 8

«std :: map是一个有序关联容器,包含具有唯一键的键值对.使用比较功能比较对键进行排序.»来自cppreference

默认比较函数std::less将在Key对象上使用运算符< .

因此,问题就出在operator<Coordinate:

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

(1, 0, 0) < (0, 1, 0)是假的,但(0, 1, 0) < (1, 0, 0)也是假的,所以就此std::map而言,(1, 0, 0) == (0, 1, 0).

为了将Coordinate对象用作a中的键std::map,您需要找到operator<满足您需求的正确严格弱排序标准().

正如其他人所说,你可以使用像std::tie(在C++ 11中)首先比较的东西x,y然后z像这样:

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;
}
Run Code Online (Sandbox Code Playgroud)