制作一个以坐标为键的std::映射
Make an std::map with a coordinate as key
创建一个以坐标为键的std::映射似乎是不可能的。当两个坐标的(x+y+z)相同时,贴图将覆盖上一个坐标。示例:
map[Coordinate(1, 0, 0)] = object1;
map[Coordinate(0, 1, 0)] = object2;
map[Coordinate(0, 0, 1)] = object3;
这将导致出现一个std::map,其中包含1个元素,其中包含object3
作为值,Coordinate(0, 0, 1)
作为键。如何防止这种情况发生,使其包含所有值?
#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;
}
};
«std::map是一个包含键值的排序关联容器与唯一密钥配对。使用比较对键进行排序函数Compare。»来自cppreference
默认的比较函数是CCD_ 3,它将使用运算符<在CCD_ 4对象上。
因此,问题在于Coordinate
:的operator<
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)
是假,但(0, 1, 0) < (1, 0, 0)
也是假,所以就std::map
而言,(1, 0, 0) == (0, 1, 0)
。
为了在std::map
中使用Coordinate
对象作为键,您需要找到满足您需求的正确的严格弱排序标准(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;
}
您的运算符<必须工作,以便所有可能的坐标都能以稳定的顺序放置。如果添加这些值,则有几种坐标组合彼此无法区分。
试试这个
friend bool operator < (const Coordinate& left, const Coordinate& right)
{
if (left.z < right.z)
{
return true;
}
else if (right.z < left.z)
{
return false;
}
else if (left.y < right.y)
{
return true;
}
else if (right.y < left.y)
{
return false;
}
else if (left.x < right.x)
{
return true;
}
else /* (right.x < left.x) */
{
return false;
}
}
为了进行比较,如果!(a < b) && !(b < a)
,则std::map
会将两个对象a
和b
视为相同对象。您的operator<
正是造成了这种歧义。首先插入(1, 0, 0)
作为密钥。接下来,您将插入并比较(0, 1, 0)
。但是,对于现有操作符,(1, 0, 0) < (0, 1, 0)
返回false
,(0, 1, 0) < (1, 0, 0)
也返回,因此两个坐标映射到同一个关键点。
- C++匿名结构作为std::映射值
- 如何从存储在std::映射中的std::集中删除元素
- 从嵌套在std::映射中的std::列表中删除元素的最佳方式
- 将唯一指针插入std::映射
- 重载std::映射不同的密钥类型
- std::映射,只有move构造函数可用
- std::映射服装比较函数和函数/lambda错误
- std::映射导致插入时出现C2664错误
- 将从std::映射中获取的std::pair引用传递给接受std::对引用的函数
- std::映射键作为模板化结构与枚举成员
- std ::映射以构造为钥匙
- 在锁定下清除STD ::映射,而移动到临时对象
- 计算向量的std ::映射为键的值,并将双倍作为值
- 写入/读取 std::映射到二进制文件需要运算符
- 我如何正确地为std ::映射分配内存
- 如何打印包含整数和整数集的std::映射
- 在字符串的std::映射中找到编译错误,long
- 将std ::映射复制到std ::对向量
- 使用std ::映射的键的部分匹配
- 遍历std ::映射,效果少于迭代器之间的比较