在哪些情况下 std::optional operator == 会导致未定义的行为?
Posted
技术标签:
【中文标题】在哪些情况下 std::optional operator == 会导致未定义的行为?【英文标题】:In which cases does std::optional operator == cause undefined behavior? 【发布时间】:2020-10-13 12:46:44 【问题描述】:Cppreference 对std::optional
的混合(可选和一些其他非可选类型)比较运算符有以下描述:
将 opt 与一个值进行比较。值进行比较(使用 T) 的对应运算符仅当 opt 包含值时。否则, opt 被认为小于值。如果对应的两路 *opt 和 value 之间的比较表达式格式不正确,或者如果 其结果不可转换为 bool,行为未定义。
让我困惑的是:
这些不规范的比较有哪些例子?
为什么编译器/STL 不直接拒绝无效的比较而不是给我们 UB?
【问题讨论】:
只是猜测:T
有一个奇怪的T::operator==
或者根本没有operator==
?不知道为什么它是 UB 而不是格式错误...
【参考方案1】:
这源于不精确的规范,此后已得到纠正。
在C++17 中,这些比较被指定为:
要求:
*x == *y
的表达式应该是格式良好的,并且它的结果应该可以转换为bool
。
Requires 是一个先决条件,因此不满足这些条件将是undefined behavior。但是有许多不同种类的“先决条件”——这是否意味着静态检查,这是否意味着如果条件不满足,则将运算符从重载集中删除,是否意味着实际的未定义行为?
在C++20 中,这些被指定为:
授权:表达式
*x == *y
是格式良好的,其结果可转换为bool
。
如果不满足条件,哪个means 程序格式错误。基本上,授权是static_assert
(或等效项)。
所以,是的,标准库有义务拒绝比较不存在或没有给你类似bool
的类型。这实际上永远不会给您带来未定义的行为(如果没有这样的运算符,实现会做什么,从/dev/random
读一点?)但现在它被更明确地指定了。
这些更改来自 Marshall Clow 题为“Mandating the Standard Library”的一系列论文,这篇论文特别来自 P1460(感谢 Marshall!)。用于指定标准库的新术语来自 Walter Brown 的“Guidelines for Formulating Library Semantics Specifications”论文 (P1369)。
【讨论】:
赞成,但我不确定你为什么引用取消引用 x 和 y 的规范,我想如果我询问只有一侧被取消引用。我认为这个限制也是为了比较 optionalFileNotFound
。以上是关于在哪些情况下 std::optional operator == 会导致未定义的行为?的主要内容,如果未能解决你的问题,请参考以下文章
C++ 标准是不是允许在没有开销的情况下实现 std::optional<double>
std::optional::value_or() - 惰性参数评估