提问人:ModernEraCaveman 提问时间:8/22/2023 更新时间:8/22/2023 访问量:52
如何使用相反的签名坐标键初始化 std::map?
How can I initialize a std::map with opposite signature coordinate keys?
问:
对于一些背景信息,我正在尝试使用字典查找创建一个快速的四叉树生成算法。基本概念涉及通过二进制表示将坐标映射到四叉树节点:
struct vec2 { // Test coordinate object
double x, y; // replacing double with signed int everywhere does not achieve results either
vec2(const double& x = NULL, const double& y = NULL)
: x(x), y(y) {}
friend std::ostream& operator<<(std::ostream& os, vec2 vector)
{
return os << "(" << vector.x << ", " << vector.y << ")\n";
}
bool operator()(const vec2& lhs, const vec2& rhs) const
{
/* TODO: make proper sorting function */
if ((lhs.x < rhs.x) && (lhs.y < rhs.y)) {
return true;
}
if (std::hypot(lhs.x, lhs.y) < std::hypot(rhs.x, rhs.y)) {
return true;
}
return false;
}
};
std::map<vec2, std::bitset<4>, vec2> nodeLoc = { // quadtree node mapping
{ ( 1, 1), 1000 }, // first quadrant
{ (-1, 1), 0100 }, // second quadrant
{ (-1,-1), 0010 }, // third quadrant
{ ( 1,-1), 0001 }, // fourth quadrant
{ ( 0, 0), 0000 },
{ ( 0, 1), 1100 }, // first and second
{ ( 0,-1), 0011 }, // third and fourth
{ ( 1, 0), 1001 }, // first and fourth
{ (-1, 0), 0110 }, // second and third
};
int main() {
std::cout << nodeLoc[(-1, -1)];
return 0;
}
main 函数应打印到控制台,但它会打印。映射函数是用 标识的,但我认为 的定义会阻止它们被标识为相同的输入。我尝试创建一个哈希函数来与 一起使用,但最终遇到了类似的问题(尽管略有不同,因为映射与 相同)。0010
1000
(-1, -1)
(1, 1)
bool operator()
std::unordered_map
(-1,1)
(1,-1)
如何在有符号坐标及其二进制节点表示之间适当地创建映射?
答:
2赞
Jan Schultke
8/22/2023
#1
编译器可以指出代码中的两个关键错误:
没有空引用
warning: converting to non-pointer type 'double' from NULL [-Wconversion-null]
9 | vec2(const double& x = NULL, const double& y = NULL)
| ^~~~
首先,你正在做的事情基本上是在代码中。C++ 中没有空引用这样的东西,这似乎是您要创建的。也不是说 a 可以绑定到临时值(临时物化),以便代码编译。const double& x = 0
const&
若要解决此问题,请完全删除构造函数,这将生成聚合类型。或者:vec2
// note: don't use default arguments because they would allow initialization
// with just one argument, which is undesirable
vec2(double x, double y) : x(x), y(y) {}
vec2() : vec2(0, 0) {}
(1, 1)
是逗号表达式,而不是构造函数调用
第二个错误是使用以下语法:
warning: left operand of comma operator has no effect [-Wunused-value]
30 | { ( 1, 1), 1000 }, // first quadrant
| ^
(1, 1)
不做,而是用逗号运算符,其中左边去掉,右边用来调用。您的原始构造函数可以只用一个参数调用,而不是 ,因此可以从 到 进行隐式转换。vec2(1, 1)
1
1
vec2(1)
explicit
1
vec2
要解决此问题,请使用 ,其中 inner 等价于 。{ { 1, 1}, 1000 }
{ 1, 1}
vec2(1, 1)
更多说明
1000
是十进制文字;初始化0b1000
std::bitset
vec2
不应是提供给 的函数对象;您可以简单地变成并使用std::map
operator()
operator<
std::map<vec2, std::bitset<4>>
- 或者,定义一个三向比较运算符
nodeLoc
应该声明为理想状态,而不是(也使用逗号运算符),而是将const
nodeLoc[(x, y)]
nodeLoc.at({x, y})
请参阅 Compiler Explorer 中的实时示例,其中包含已实现的所有更改
评论
(0, 1)
是。。只是(涉及逗号运算符。1
{0, 1}
bitset
"1000"
0b1000
1000
0001
0100
1
100
1000
bitset<4>
0100
64
bool operator()(const vec2& lhs, const vec2& rhs) const { return std::tie(lhs.x, lhs.y) < std::tie(rhs.x, rhs.y);
auto operator <=>(const vec2& rhs) const = default