如何使用相反的签名坐标键初始化 std::map ?

问题描述 投票:0回答:1

对于一些背景信息,我正在尝试使用字典查找创建快速四叉树生成算法。基本概念涉及通过二进制表示将坐标映射到四叉树节点:

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;
}

主函数应该将

0010
打印到控制台,但它却打印
1000
。地图函数将
(-1, -1)
(1, 1)
进行识别,但我认为
bool operator()
的定义会阻止它们被识别为相同的输入。我尝试创建一个与
std::unordered_map
一起使用的哈希函数,但最终遇到了类似的问题(尽管有点不同,因为
(-1,1)
会映射为与
(1,-1)
相同的映射)。

如何在有符号坐标与其二进制节点表示之间正确创建映射?

c++ coordinates std comparator stdmap
1个回答
0
投票

编译器可以指出代码中的两个关键错误:

没有空引用

<source>:9:28: warning: converting to non-pointer type 'double' from NULL [-Wconversion-null]
    9 |     vec2(const double& x = NULL, const double& y = NULL)
      |                            ^~~~

首先,您所做的本质上是该代码中的

const double& x = 0
。 C++ 中不存在空引用之类的东西,这看起来就像您想要创建的那样。也不是说
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)
是逗号表达式,而不是构造函数调用

第二个错误是使用这种语法:

<source>:30:17: 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
进行隐式转换。

要解决此问题,请使用

{ { 1, 1}, 1000 }
,其中内部
{ 1, 1}
相当于
vec2(1, 1)

进一步说明

  • vec2
    不应该是提供给
    std::map
    的函数对象;您只需将
    operator()
    转换为
    operator<
    并使用
    std::map<vec2, std::bitset<4>>
  • 理想情况下,
  • nodeLoc
    应声明为
    const
    ,而不是
    nodeLoc[(x, y)]
    (也使用逗号运算符),请编写
    nodeLoc.at(x, y)
© www.soinside.com 2019 - 2024. All rights reserved.