问题描述
|
我如何使用以下结构:
struct point
{
int x;
int y;
int z;
};
作为std::map<point,bool>
的钥匙?如何为两点定义operator<
?
解决方法
诸如ѭ3之类的标准库容器要求您的订购是“严格弱订购”,因此在设计容器时必须非常小心。
三元组的典型方法如下所示:
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
。如果它们相同,那么类似地,您将陷入“ 8”比较。
,当然,ѭ9将使这完全没有必要。
更新这里添加了全包式的“吃不饱”的解决方案。恕我直言,它摇滚!
#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,z) < boost::tie(rhs.x,rhs.y,rhs.z);
}
};
关键在于:这一切都可以优化。编译:
int main()
{
point a(1,2,3),b(3,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:
编译器能够将整个程序优化为有效……13%。那太整齐了。
简单答案如下:
struct point
{
point(int x,int z)
: x(x),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);
}
,一种懒惰的方法:
bool operator<( point const &pt ) const
{
return ::boost::make_tuple(x,z) <
::boost::make_tuple(pt.x,pt.y,pt.z);
}
,最简单的写法是这样的:
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;
}
,如果应该以某种方式订购它们,则需要指定确切的方式(例如,从0/0/0到欧氏距离)。如果您只想区分不同点,则可以执行以下操作
x == x2 ? (y == y2 ? (z < z2) : y < y2) : x < x2
,只是猜测,
bool operator<(const point& other) const
{
return( memcmp( (void*) this,(void*) &other,sizeof(point)) < 0);
}
当然,由于x,y和z是带符号的值,所以这种顺序有点奇怪,但这应该适合于将其放入std :: map中,不是吗?