如何使用以下结构:
struct point
{
int x;
int y;
int z;
};
作为std::map<point, bool>
的关键?我应该如何定义operator<
两点?
答案 0 :(得分:18)
std::map
等标准库容器要求您的订购是“严格弱排序”,因此在设计时必须非常小心。
3-ary元组的典型方法如下:
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
相同,那么你就可以比较y
了。如果它们相同,那么同样地,您将进入z
比较。
答案 1 :(得分:6)
当然,boost::tuple<int,int,int>
会使这完全没必要。
更新在此处添加全包式的“吃蛋糕,吃得太多 - 无瑕疵”的解决方案。恕我直言,它摇滚!
#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);
}
答案 2 :(得分:1)
一种懒惰的方式:
bool operator<( point const &pt ) const
{
return ::boost::make_tuple(x,y,z) <
::boost::make_tuple(pt.x,pt.y,pt.z);
}
答案 3 :(得分:0)
最简单的写法是这样的:
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;
}
答案 4 :(得分:0)
如果它们应该以某种方式排序,你需要指定那种确切的方式(例如,距离0/0/0的欧几里德距离)。如果您只想区分不同的点,您可以执行类似
的操作x == x2 ? (y == y2 ? (z < z2) : y < y2) : x < x2
答案 5 :(得分:-1)
猜猜伙计们,
bool operator<(const point& other) const
{
return( memcmp( (void*) this, (void*) &other, sizeof(point)) < 0);
}
当然,顺序有点奇怪,因为x,y和z都是有符号值,但是这应该适合订购到std :: map,不是吗?