如何使用 std::map 将 bool 映射到 3d 点结构?
Posted
技术标签:
【中文标题】如何使用 std::map 将 bool 映射到 3d 点结构?【英文标题】:How to map a bool to a 3d point struct with std::map? 【发布时间】:2011-05-24 11:05:26 【问题描述】:如何使用以下结构:
struct point
int x;
int y;
int z;
;
作为std::map<point, bool>
的键?我应该如何为两点定义operator<
?
【问题讨论】:
您希望如何订购积分?还是顺序不重要? @Space_C0wb0y:它至少必须是严格的弱排序。 Operator< and strict weak ordering的可能重复 您确定不希望地图中相邻的点在此 3D 空间中彼此靠近?因为那样你就需要分形映射,实现起来要复杂得多。 +1 这个问题无论如何是因为 (a) 显然,具有很高声誉的编码人员会经常执行这个错误,即使无法理解 弱严格排序 (b) 即使我学到了一个有价值的过程中的技巧\ 【参考方案1】:像std::map
这样的标准库容器要求您的排序是“严格弱排序”,因此在设计时必须非常小心。
三元元组的典型方法如下所示:
bool operator<(const point& other) const
if (x != other.x)
return (x < other.x);
if (y != other.y)
return (y < other.y);
return (z < other.z);
它就像一个只用于x
的比较器,但不同之处在于,如果两个x
s 相同,那么您将无法比较y
s。如果它们是相同的,那么您同样会陷入z
比较。
【讨论】:
Strict Weak Ordering
是矛盾的? :P
@Nawaz:不; “严格”和“弱”是正交的(我认为您将“严格”与“强”混淆,或将“弱”与“放松”混淆)。 Have a read of this.
感谢您的解释和链接。 (顺便说一句,我的评论是为了娱乐。悲伤:()
@Nawaz:哦,哎呀。我有时会为你的讽刺而挣扎;)【参考方案2】:
当然,boost::tuple<int,int,int>
会让这完全没有必要。
更新 在此处添加包罗万象的 have-your-cake-and-eat-it-it-too 无缺点解决方案。恕我直言,它摇滚!
#include <boost/tuple/tuple_comparison.hpp>
struct point
int x, y, z;
point(int x, int y, int z) : x(x), y(y), z(z)
bool operator<(const point& rhs) const
return boost::tie(x, y, z) < boost::tie(rhs.x, rhs.y, rhs.z);
;
这是最重要的:一切都被优化了。编译:
int main()
point a(1,2,3), b(3,2,1);
bool lt = a<b;
return lt?0:255;
使用 g++ -O2 在汇编中产生以下结果。
main:
.LFB1132:
pushl %ebp
xorl %eax, %eax
movl %esp, %ebp
popl %ebp
ret
.LFE1132:
编译器能够有效地将整个程序优化为 ...return 0
。这很整洁。
答案很简单:
struct point
point(int x, int y, int z)
: x(x), y(y), z(z)
int x;
int y;
int z;
bool operator<(const point& rhs) const
if (x<rhs.x) return true;
if (x==rhs.x)
if (y<rhs.y) return true;
if (y==rhs.y) return z<rhs.z;
return false;
;
另外,我会考虑寻找允许使用 std::lexicographical_compare 的结构的重新定义
#include <algorithm>
// ...
bool operator<(const point& rhs) const
return std::lexicographical_compare(&xyz, &xyz+3, &rhs.xyz, &rhs.xyz+3);
【讨论】:
通过将构造函数添加到结构point
,您使其成为非 POD。它以前是 POD。
@finnw: POD 不能有 user-defined 构造函数。见Can't C++ POD type have any constructor?
@finnw, @Nawaz:关于 POD 结构的要点(删除“推荐”)。但是,我添加了一个基于来自 Boost Tuple 的 boost::tie() 的脑电波。它完全消除了竞争:)
@finnw:你不应该删除评论。它对其他人有帮助。删除使讨论看起来很奇怪。 :P【参考方案3】:
一种懒惰的方法:
bool operator<( point const &pt ) const
return ::boost::make_tuple(x,y,z) <
::boost::make_tuple(pt.x,pt.y,pt.z);
【讨论】:
这给了我一个绝妙的主意,我会在测试后 5 分钟内更新我的答案!tie
会不会更好更快?
@Xeo,我不知道。它创建一个临时的引用结构,而不是一个临时的值结构。两者都可以被编译器优化掉。但如果不是,那么您已经引入了额外的间接层。
@Xeo:我们的想法又一次相似了,见***.com/questions/6109445/…;那是那里的一些优化壮举! (当然我需要在发布基于tie()
的解决方案之前查看反汇编!)【参考方案4】:
最简单的写法是这样的:
bool operator<(const point& p) const
if(x < p.x)
return true;
else if(p.x < x)
return false;
if( y < p.y)
return true;
else if( p.y < y)
return false;
if( z < p.z)
return true;
else if(p.z < z)
return false;
return false;
【讨论】:
没有。这不满足严格的弱排序。 @Tomalak:谢谢指点。我编辑了代码。现在正确了吗? 是的,我相信是的。比较冗长! 我的版本(两个)都更短更简单,所以我不能完全同意【参考方案5】:如果它们应该以某种方式排序,您需要指定确切的方式(例如通过从 0/0/0 的欧几里德距离)。如果你只想区分不同的点,你可以这样做
x == x2 ? (y == y2 ? (z < z2) : y < y2) : x < x2
【讨论】:
没有。如果x
s 不等于,您应该只使用y
的情况。如果x > x2
,则立即回复false
。【参考方案6】:
只是猜测,
bool operator<(const point& other) const
return( memcmp( (void*) this, (void*) &other, sizeof(point)) < 0);
当然,顺序有点奇怪,因为 x,y 和 z 是有符号值,但这应该适合排序到 std::map 中,不是吗?
【讨论】:
你到底在做什么? >. 我认为你应该考虑这个解决方案。 我可以提供更多代码,但您仍然对此持怀疑态度。但由于point
结构仅包含 3 个 int 并且是不是虚拟的,因此结构的大小是 3 int 长,(void*)
转换将 compare 方法放在第一个 int 上!比较 3 个 aligned int
的内存打印是一种比较它们与唯一性保证的方法。以上是关于如何使用 std::map 将 bool 映射到 3d 点结构?的主要内容,如果未能解决你的问题,请参考以下文章
C++ 将预先保留的哈希映射(std::unordered_map)与整数键和连续数据数组(std::vector)进行比较
将 JNI -> jobject(基本上是映射和/或 java 文件中的映射)转换为 std::map(c++)