Operator<和严格的弱排序

问题描述 投票:4回答:0

如何定义 operator< 在n-tuple上(例如在3-tuple上),使其满足 严格弱排序 概念?我知道boost库的元组类有正确定义的 operator< 但由于某些原因,我无法使用它。

c++ stl
40
投票
if (a1 < b1)
  return true;
if (b1 < a1)
  return false;

// a1==b1: continue with element 2
if (a2 < b2)
  return true;
if (b2 < a2)
  return false;

// a2 == b2: continue with element 3
if (a3 < b3)
  return true;
return false; // early out

这将元素按a1最重要和a3最不重要排序。

这可以无限地继续下去,你也可以将它应用于一个T的向量,迭代比较a[i] < a[i+1] a[i+1] < a[i]。该算法的另一种表达方式是 "跳过同时相等,然后比较"。

while (i<count-1 && !(a[i] < a[i+1]) && !(a[i+1] < a[i])
  ++i;
return i < count-1 && a[i] < a[i+1];

当然,如果比较的成本很高,你可能会想要缓存比较的结果。


编辑]删除了错误的代码


[编辑]如果不仅仅是 operator< 的模式,我倾向于使用

if (a1 != b1)
  return a1 < b1;

if (a2 != b2)
  return a2 < b2;

...

54
投票

严格弱排序

这是一个数学术语,用来定义两个物体之间的关系。其定义是:

如果f(x, y)和f(y, x)都是假的,那么两个对象x和y是等价的。请注意,一个对象总是(根据不屈性不变性)等同于自身。

在C++中,这意味着如果你有两个给定类型的对象,当你与操作符<比较时,你应该返回以下值。

X    a;
X    b;

Condition:                  Test:     Result
a is equivalent to b:       a < b     false
a is equivalent to b        b < a     false

a is less than b            a < b     true
a is less than b            b < a     false

b is less than a            a < b     false
b is less than a            b < a     true

如何定义不等价完全取决于你的对象的类型。

形式上的定义。严格的弱排序

计算机科学。严格的弱排序

它与运营商的关系。比较器


31
投票

...一个老问题的新答案,但现有的答案没有从C++11中找到简单的解决方案...

C++11的解决方案

C++11以后提供了 std::tuple<T...>,你可以用它来存储你的数据。 tuple的数据有一个匹配的 operator< 首先比较最左边的元素,然后沿着元组工作,直到结果明确。 这适合于提供 严格弱排序 预期的,如 std::setstd::map.

如果你在其他变量中也有数据(例如在 struct),你甚至可以使用 std::tie() 以创建一个元组 参考文献,然后可以将其与另一个这样的元组进行比较。 这样就很容易写出 operator< 中的特定成员数据字段。classstruct 类型。

struct My_Struct
{
    int a_;
    double b_;
    std::string c_;
};

bool operator<(const My_Struct& lhs, const My_Struct& rhs)
{
    return std::tie(lhs.a_, lhs.b_, lhs.c_) < std::tie(rhs.a_, rhs.b_, rhs.c_);
}

6
投票

你可以简单地使用三元素向量,它已经有operator<()的适当定义。这样做的好处是,它可以扩展到N元素,而不需要你做任何事情。


5
投票

基本流程应该是这样的。如果第K个元素不同,返回哪个元素小,否则转到下一个元素。. 下面的代码假设你 不要 有一个提升元组,否则你将使用 get<N>(tuple) 而不是一开始就有这个问题。

if (lhs.first != rhs.first)
    return lhs.first < rhs.first;                
if (lhs.second != rhs.second)
    return lhs.second< rhs.second;
return lhs.third < rhs.third;

2
投票

即使你不能使用boost版本,你也应该可以把这段代码移植过来。 我从std::pair里偷了这个--我想3元组也会类似。

return (_Left.first < _Right.first ||
        !(_Right.first < _Left.first) && _Left.second < _Right.second);

编辑: 正如一些人所指出的,如果你从标准库中偷取代码用于你的代码,你应该重命名那些前面有下划线的东西,因为这些名字是保留的。

© www.soinside.com 2019 - 2024. All rights reserved.