操作者<比较多个字段(operator< comparing multiple fiel

2019-06-26 00:27发布

我有以下操作者<是应该由第一值进行排序,然后通过另一个值:

    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.field1a.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