'<'的首选实现用于多变量结构

时间:2009-12-12 05:10:11

标签: c++ language-agnostic comparison

最初这可能看起来过于抽象或哲学,但我真的很想知道某人是否有一个令人信服的论据支持一个实现而不是另一个。

operator<给出std::pair<T1, T2>,这将是更好的实现:

return x.first < y.first ||
       x.first == y.first && x.second < y.second;

或:

return x.first < y.first ||
       !(y.first < x.first) && x.second < y.second;

我的理解是这两个实现产生了相同的结果。后者是首选,因为它仅以operator<来定义?或者假设一个低于可比性的类型也应该是可比性的是否合法?有没有人看到另一个会在一个或另一个之间摇摆你的观点?

当然,任何答案都应该是通用的和可扩展的。那么你会使用哪一个?为什么?有没有比上面更好的实现?

3 个答案:

答案 0 :(得分:13)

假设对于任何类型,如果它小于可比较,那么它也是可比的,这是不合理的,因为可以重载operator<但不会重载{{1 }}

因此,如果您预计必须处理用户定义的类型,则第二种方法更可取。但是,您应该添加一些括号来阐明操作的顺序:

operator==

答案 1 :(得分:4)

如果运算符&lt;代表弱序。例如,假设T1的对象是有向图中的节点,而T1a < T1d意味着“T1a是图中T1b的祖先”(这不是一种不常见的符号)。

然后:!(T1b < T1a)意味着“t1b不是t1a的祖先”所以:

  1. t1a是t1b的祖先(由第一次测试排除)
  2. t1a与t1b
  3. 是同一个节点
  4. t1a和t1b无法比较(即他们是兄弟姐妹)
  5. 这第三种情况非常重要。在这种情况下,您可能需要运算符&lt;在对上返回false,但它可能不会。

    (对一组元素的弱排序意味着a <= bb <= a都可以为假。)

    就个人而言,我并不喜欢运算符重载,特别是在使用泛型时。程序员倾向于假设并不总是保持良好的“算术”属性。

答案 2 :(得分:2)

我会使用第二个,因为这是标准指定的内容!

正如其他人提到的那样,只要<定义了两种类型的总排序,==<一致,这两个定义就是等价的。但是当其中任何一个不成立时,差异是可观察的,如果你使用了第一个定义,那就不符合。

编辑:标准定义在某种意义上优于您的第一个定义:如果<在T1和T2上定义了严格的弱排序,那么标准定义会给出严格的弱定义在pair<T1, T2>订购。你的第一个定义没有,这可能会导致真正的问题。例如,假设我们有x和y,既不x < y也不y < x。然后考虑对a[3] = {P(x, 2), P(y, 1), P(x, 1)}对的数组。显然,我们应该说这个数组按升序排序,因为a[2] < a[0]。但是,如果我们使用您的第一个定义,std::is_sorted将得出结论 排序,因为没有两个连续元素具有可比性。第一个定义不是严格的弱排序这一事实打破了算法。在标准定义P(y, 1) < P(x, 2)下,算法检测到数组未按需要排序。

(这个答案以前对这种情况的分析完全不正确 - 抱歉!)