我有以下操作者<是应该由第一值进行排序,然后通过另一个值:
inline bool operator < (const obj& a, const obj& b)
{
if(a.field1< b.field1)
return true;
else
return a.field2 < b.field2;
}
我有一种感觉,这是不正确的,你不能这样做,没有对成员变量,另外三分之一comparaison测试,但我找不到在哪里,这并不工作的任何例子。 所以,这个对子级排序真的如预期? 谢谢
编辑:我会编码它:
inline bool operator < (const obj& a, const obj& b)
{
if(a.field1< b.field1)
return true;
else if(a.field1> b.field1)
return false;
else
return a.field2 < b.field2;
}
有什么区别? 我问,因为我知道我是从经验中正确的,但也比第一次长
Answer 1:
我想都是由我自己做..
您应该只比较值Obj::field2
,如果值Obj::field1
是相等的。
这种易于理解的方式:
/* This will meet the requirements of Strict-Weak-Ordering */
if (a.field1 != b.field1) return a.field1 < b.field1;
else return a.field2 < b.field2;
正确的(推荐)的方式:
实现它的“ 正确 ”的方式只使用operator<
来比较的字段,下面看起来复杂得多,它确实是。
然而,它会产生相同的结果之前写入的容易理解的例子。
return a.field1 < b.field1 || (
!(b.field1 < a.field1) && a.field2 < b.field2
);
必须有实现的一种方式operator<
而不引起了很多头疼的?
C ++ 11
可以使用std::tuple
从该已有的STL operator<
用于定义多个字段,如在下面的例子。
#include <utility>
...
inline bool
operator< (Obj const& lhs, Obj const& rhs)
{
return std::tie (lhs.field1, lhs.field2) < std::tie (rhs.field1, rhs.field);
}
C ++ 03
如果你的编译器没有为C ++ 11的支持还没有,你只需要比较来自两个领域的对象,您可以使用std::pair
代替。
其原因std::make_pair
是一样的使用前面例子中std::tie
。
#include <utility>
...
inline bool
operator< (Obj const& lhs, Obj const& rhs)
{
return std::make_pair (lhs.field1, lhs.field2)
< std::make_pair (rhs.field1, rhs.field2);
}
使用std::pair
将需要要创建的成员的拷贝,这在某些情况下是不希望的。
这真的是值得推荐的做法?
更多信息请参见下面的问题/答案,但概括起来; 在C ++ 11做法不会引起那么多的开销,这是很容易实现。
Answer 2:
想想,如果发生了什么a.field1
大于b.field1
但a.field2
小于b.field2
。 在这种情况下,你比较仅基于field2
这是不是你想要的。
你只希望把field2
发挥在field1
字段是平等的,所以你要找的东西是一样的东西(伪代码):
if a.field1 < b.field1: return true
if a.field1 > b.field1: return false
# field1s is equal here.
return a.field2 < b.field2
Answer 3:
不,你还需要搭上(a.field1 > b.field1)
这不是一个严格的弱序,因为它会给(1,2) < (2,1)
而且(2,1) < (1,2)
Answer 4:
下面是依赖于逻辑短路规则,以避免明确的分支版本
template<typename T>
bool operator< (T const& a, T const& b)
{
return (
( a.field1 < b.field1 ) || (( a.field1 == b.field1 ) &&
( a.field2 < b.field2 ))
);
}
这是假设你的原始类型的field1
具有的operator==
。 变得乏味超过2个字段中键入这一点,但可以使用std::lexicographical_compare
如果你的类obj
存储的字段内std::array<T, N>
对于一些类型T
和尺寸N
template<typename T, int N>
struct obj
{
std::array<T, N> field;
};
bool operator< (obj const& a, T const& b)
{
return std::lexicographical_compare(
a.field.begin(), a.field.end(),
b.field.begin(), b.field.end()
);
}
请注意,有一个文件草案N3326 ,讨论添加操作员==
和<
自动类类型。
Answer 5:
下面描述我的方法涉及一些宏,但在许多情况下还是有用的。 也许这样的事情可以用内联函数来也做了。
#define CMP_LT2(a, b) ((a) < (b) ? (a) : (b))
#define CMP_GT2(a, b) ((a) > (b) ? (a) : (b))
#define CMP_LTE2(a, b) ((a) <= (b) ? (a) : (b))
#define CMP_GTE2(a, b) ((a) >= (b) ? (a) : (b))
#define CMP_EQ2(a, b) ((a) == (b))
#define CMP_NEQ2(a, b) ((a) != (b))
#define CMP_LT3(a, b, c) (CMP_EQ2(a, b) ? (c) : CMP_LT2(a, b))
#define CMP_GT3(a, b, c) (CMP_EQ2(a, b) ? (c) : CMP_GT2(a, b))
#define CMP_LTE3(a, b, c) (CMP_EQ2(a, b) ? (c) : CMP_LT2(a, b))
#define CMP_GTE3(a, b, c) (CMP_EQ2(a, b) ? (c) : CMP_GT2(a, b))
#define CMP_EQ3(a, b, c) ((a) == (b) ? (c) : false)
#define CMP_NEQ3(a, b, c) ((a) != (b) ? true : (c))
然后,假设你有:
struct Point3D {
double x;
double y;
double z;
};
然后你写的:
struct Point3D {
double x;
double y;
double z;
bool operator<(const Point3D& other) const noexcept
{
return CMP_LT3(z, other.z,
CMP_LT3(y, other.y,
CMP_LT2(x, other.x)));
}
};
文章来源: operator< comparing multiple fields