operator <比较多个字段

lez*_*lon 17 c++ lexicographic comparison-operators

我有以下运算符<应该首先按值排序,然后按另一个值排序:

    inline bool operator < (const obj& a, const obj& b) 
    {
        if(a.field1< b.field1)
            return true;
        else
            return a.field2 < b.field2;
    }
Run Code Online (Sandbox Code Playgroud)

我觉得这是不正确的,如果没有对成员变量进行另一次第三次比较测试,你就不能这样做,但我找不到任何不起作用的例子.那么这真的和预期的一样吗?谢谢

编辑:我会把它编码为:

    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;
    }
Run Code Online (Sandbox Code Playgroud)

有什么不同吗?我问,因为我知道我的经验是正确的,但也比第一个更长

Fil*_*efp 35

我想自己做这一切..

您应该只比较值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;
Run Code Online (Sandbox Code Playgroud)

正确的(推荐的)方式:

实现它的" 正确 "方式仅operator<用于比较字段,下面看起来比实际更复杂.

然而,它将产生与先前编写的易于理解的示例相同的结果.

return a.field1 < b.field1 || (
  !(b.field1 < a.field1) && a.field2 < b.field2
);
Run Code Online (Sandbox Code Playgroud)

必须有一种实施方式而operator<不会引起很多头痛?

C++ 11

您可以使用已经定义的多个字段std::tupleSTLoperator<,例如下面的示例.

#include <utility>

...

inline bool
operator< (Obj const& lhs, Obj const& rhs)
{
  return std::tie (lhs.field1, lhs.field2) < std::tie (rhs.field1, rhs.field);
}
Run Code Online (Sandbox Code Playgroud)

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);
}
Run Code Online (Sandbox Code Playgroud)

使用std::pair将需要创建成员的副本,这在某些情况下是不合需要的.

这是真的推荐的做法吗?

有关详细信息,请参阅以下问题/答案,但总结一下; c ++ 11方法不会产生太多开销,而且实现起来非常简单.

  • 写这种情况的"规范"方式是"返回a.field1 <b.field1 ||" (!(b.field1 <a.field1)&& a.field2 <b.field2)`.Canonical主要是因为它只使用`<`; 在实践中,我发现它并不清楚,并且只会在库模板的上下文中使用它(我不希望对除标准库所需的类型之外的类型强加任何其他约束). (3认同)
  • 或者`return(a.field1 == b.field1)?a.field2 <b.field2:a.field1 <b.field1;`. (2认同)

pax*_*blo 7

想想如果a.field1大于b.field1a.field2小于的话会发生什么b.field2.在这种情况下,你根据field2你想要的东西进行比较.

你只想field2field1字段相等的地方发挥作用,所以你要找的是(伪代码):

if a.field1 < b.field1: return true
if a.field1 > b.field1: return false
# field1s is equal here.
return a.field2 < b.field2
Run Code Online (Sandbox Code Playgroud)