考虑以下代码:
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 弱排序的要求。但是,标准是否明确标记将这样的比较器传递为未定义的行为?
答案 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]
- 25.3中的所有操作都有两个版本:一个采用Compare类型的函数对象,另一个使用 运营商LT;
- 比较用作函数对象,如果第一个参数小于第二个参数,则返回true,并返回false 除此以外。比较comp用于假设有序关系的算法。假设comp 不会通过解引用的迭代器应用任何非常量函数。
- 对于所有采用比较的算法,有一个版本使用运算符&lt;代替。也就是说,comp(* i,* j)!= false默认为* i&lt; * j!= false。对于25.3.3 中描述的算法以外的算法,以便正常工作,comp具有 对价值观产生严格的弱排序。
- 术语严格指的是反自由关系的要求(!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)[注意:在这些条件下,可以证明
- equiv是等价关系
- comp在由等式
确定的等价类上引起明确定义的关系- 诱导关系是严格的总排序。 - 尾注]