std :: sort - 传递错误的比较器未定义的行为?

时间:2016-01-17 01:33:03

标签: c++ stl undefined-behavior

考虑以下代码:

std::sort(vec.begin(), vec.end(),
    [](const Foo& lhs, const Foo& rhs) { return !(lhs < rhs); }
);

如果lhs == rhs,lambda(lhs,rhs)和lambda(rhs,lhs)都将返回true,这违反了提供 strict 弱排序的要求。但是,标准是否明确标记将这样的比较器传递为未定义的行为?

3 个答案:

答案 0 :(得分:4)

警告:遵循极端语言律师。

the most recent draft of the standard的措辞在[alg.sorting] p3中这样说:

  

对于采用Compare的所有算法,都有一个使用operator<的版本。也就是说,comp(*i, *j) != false默认为*i < *j != false。对于25.4.3中描述的算法以外的算法,comp   应对这些价值观产生严格的弱序。

使用&#34; shall&#34;,标准为implicitly stating that violating it leads to undefined behavior

这是否要求给定的函数对所有可能的值强制执行SWO,或者只是为算法赋予的值,标准中并不清楚。但是,由于限制是在一个讨论那些特定算法的段落中说明的,因此假设它指的是提供给算法的值范围是不合理的。

否则,由于NaN,默认operator<无法为float强加SWO。

答案 1 :(得分:1)

  

[alg.sorting] / 3 对于25.4.3中描述的算法以外的算法   正确地说,comp必须对值进行严格的弱排序。

     

[alg.sorting] / 4 术语 strict 指的是反身关系的要求(!comp(x, x)对所有x)。 ..

您的比较谓词不是严格的弱序。

答案 2 :(得分:1)

Why will std::sort crash if the comparison function is not as operator <?已经有人问过这个问题。

至少该帖子中提出问题的人声称已收到例外

总结这里的标准,我突出了与问题相关的部分。现在,“正常工作”的反义词可以被解释为“未定义的行为”。

  

25.3排序和相关操作[alg.sorting]

     
      
  1. 25.3中的所有操作都有两个版本:一个采用Compare类型的函数对象,另一个使用   运营商LT;
  2.   
  3. 比较用作函数对象,如果第一个参数小于第二个参数,则返回true,并返回false   除此以外。比较comp用于假设有序关系的算法。假设comp   不会通过解引用的迭代器应用任何非常量函数。
  4.   
  5. 对于所有采用比较的算法,有一个版本使用运算符&lt;代替。也就是说,comp(* i,* j)!=   false默认为* i&lt; * j!= false。对于25.3.3 中描述的算法以外的算法,以便正常工作,comp具有   对价值观产生严格的弱排序。
  6.   
  7. 术语严格指的是反自由关系的要求(!comp(x,x)对所有x),并且术语弱到   要求不像总排序那样强,但强于部分排序的要求。要是我们   将equiv(a,b)定义为!comp(a,b)&amp;&amp; !comp(b,a),那么要求是comp和equiv都是   传递关系:      
        
    • comp(a,b)&amp;&amp; comp(b,c)表示comp(a,c)
    •   
    • equiv(a,b)&amp;&amp;等式(b,c)暗示等式(a,c)[注意:在这些条件下,可以证明      
          
      1. equiv是等价关系
      2.   
      3. comp在由等式
      4. 确定的等价类上引起明确定义的关系   
      5. 诱导关系是严格的总排序。 - 尾注]
      6.   
    •   
  8.