std::sort - 正在传递错误的比较器未定义的行为
std::sort - is passing a faulty comparator 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,这违反了提供严格弱排序的要求。但是,该标准是否明确将通过这样的比较器标记为未定义的行为?
警告:极端的语言律师随之而来。
该标准的最新草案的措辞在[alg.sorting]p3中是这样说的:
对于所有需要
Compare
的算法,有一个版本使用operator<
代替。也就是说,comp(*i, *j) != false
默认为*i < *j != false
.对于 25.4.3 中描述的算法以外的算法,comp 应诱导对值进行严格的弱排序。
通过使用"应"一词,该标准含蓄地指出,违反它会导致未定义的行为。
这是否要求给定函数对所有可能的值施加SWO,或者仅针对给定算法的值,这在标准中尚不清楚。但是,由于限制是在讨论这些特定算法的段落中陈述的,因此假设它指的是提供给算法的值范围并不是没有道理的。
否则,由于 NaN,默认operator<
无法在 float
秒内强加 SWO。
这已经在 为什么 std::sort 崩溃如果比较函数不像运算符<?中得到了回答。
至少该线程中提出该问题的人声称收到了例外。
为了从标准中总结一下,我强调了与问题相关的部分。现在,"正常工作"的反义词可以解释为"未定义的行为"。
25.3 排序及相关操作
- 25.3 中的所有操作都有两个版本:一个采用 Compare 类型的函数对象,另一个使用 操作员<。
- 比较用作函数对象,如果第一个参数小于第二个参数,则返回 true,如果返回 false 否则。比较 comp 始终用于假设排序关系的算法。假设 comp 不会通过取消引用的迭代器应用任何非常量函数。
- 对于所有采用比较的算法,有一个版本改用运算符<。也就是说,comp (*i, *j) != false 默认为 *i <*j != false。对于 25.3.3 中描述的算法以外的算法正常工作,comp 具有 以诱导对值进行严格的弱排序。
- 术语"严格"是指对非反身关系的要求(!comp (x, x) 表示所有 x),术语弱 要求不如总排序强,但比部分排序的要求强。如果我们 将 equiv(a, b) 定义为 !comp (a, b) && !comp (b, a),那么要求是 comp 和 equiv 都是 传递关系:
- comp (a, b) && comp (b, c) 意味着 comp (a, c)
equiv(a, b) && equiv(b, c)- 表示 equiv(a, c) [ 注意:在这些条件下,可以证明
- 等价是等价关系
- comp 在等价类上诱导出由 equiv 确定的明确定义的关系
- 诱导关系是一个严格的总排序。 —尾注 ]
[alg.sorting]/3 用于 25.4.3 中描述的算法以外的算法工作 正确地,
comp
必须对值进行严格的弱排序。[alg.sorting]/4 术语严格是指对所有
x
的不可反身关系(!comp(x, x)
)的要求......
您的比较谓词不是严格的弱排序。
- std::设置自定义比较器
- 带自定义比较器的最小优先级队列
- 优先级队列自定义比较器
- 链接器错误:未定义对"Reference_Genome::seq[abi:cxx11]"的引用
- 什么是自定义比较器以及如何在 C++ 的排序函数中使用它?
- 没有默认构造函数作为模板参数的自定义比较器
- 只有级联分类器会发出未定义的引用错误
- Windows 链接器是否使用 LoadLibrary 解析 DLL 中未定义的符号?
- set_intersection使用自定义设置比较器
- "未定义对'WinMain@16'的引用"gcc 编辑器中的错误
- SWIG链接器:未定义符号:_ZN2cv8fastFreeEPv(cv::fastFree(void*))
- CLang++ 链接器未定义的符号用于体系结构x86_64
- std::map 的比较器函数中的 SEG 故障/未定义行为
- C++GL链接器未定义引用
- std::sort - 正在传递错误的比较器未定义的行为
- 是什么使得这些迭代器比较具有未定义的行为
- 奇怪的编译器错误,说明我的迭代器未定义
- c++指针比较器未编译
- Qt设计器未定义符号与自定义小部件插件
- 链接器未定义符号错误