运营商<和严格的弱秩序
如何在n元组(例如3元组)上定义operator<
它满足严格的弱排序概念? 我知道boost库具有正确定义的operator<
元组类,但由于某些原因,我无法使用它。
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指定的元素最重要,最不重要的。
这可以继续无限的,你也可以例如将它应用于T的向量,迭代比较[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];
当然,如果比较费用昂贵,您可能需要缓存比较结果。
删除了错误的代码
严格的弱排序
这是定义两个对象之间关系的数学术语。
其定义是:
如果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 bb < a false a is less than ba < b true a is less than bb < a false b is less than aa < b false b is less than ab < a true
你如何定义等价/更少完全取决于你的对象的类型。
查看关于这个主题的SGI页面:
http://www.sgi.com/tech/stl/StrictWeakOrdering.html
…一个很老的问题的新答案,但现有的答案错过了C ++ 11的简单解决方案…
C ++ 11解决方案
C ++ 11向前提供了std::tuple<T...>
,你可以使用它来存储你的数据。 tuple
s有一个匹配的operator<
最初比较最左边的元素,然后沿着元组工作,直到结果清晰。 这适合于提供例如std::set
和std::map
期望的严格的弱顺序 。
如果你有一些其他变量的数据(例如struct
字段),甚至可以使用std::tie()
创建一个引用元组,然后可以将这个元组与另一个这样的元组进行比较。 这样可以很容易地为用户定义的class
/ struct
类型中的特定成员数据字段写入operator<
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_); }
你可以简单地使用三元素向量,它已经有适当定义的operator <()了。 这有一个好处,就是它不需要做任何事情就可以扩展到N元素。
基本流程应该是: 如果第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;
即使你不能使用boost版本,你也应该能够对代码进行剔除。 我从std :: pair中挑出了这个 – 一个3元组将会类似我猜。
return (_Left.first < _Right.first || !(_Right.first < _Left.first) && _Left.second < _Right.second);
编辑:正如一些人已经指出的,如果你从标准库中窃取代码来使用你的代码,你应该重命名前面有下划线的东西,因为这些名字是保留的。