Cppreference具有以下混合(可选和一些其他非可选类型)比较运算符的描述std::optional
:
将 opt 与值进行比较。只有当 opt 包含一个值时,才会比较这些值(使用 T 的相应运算符)。否则, opt 被认为小于值。如果 *opt 和 value 之间对应的双向比较表达式格式不正确,或者其结果不能转换为 bool,则行为未定义。
这里让我感到困惑的是:
这些格式不正确的比较的例子是什么?
为什么编译器/STL 不拒绝无效的比较而不是给我们 UB?
Cppreference具有以下混合(可选和一些其他非可选类型)比较运算符的描述std::optional
:
将 opt 与值进行比较。只有当 opt 包含一个值时,才会比较这些值(使用 T 的相应运算符)。否则, opt 被认为小于值。如果 *opt 和 value 之间对应的双向比较表达式格式不正确,或者其结果不能转换为 bool,则行为未定义。
这里让我感到困惑的是:
这些格式不正确的比较的例子是什么?
为什么编译器/STL 不拒绝无效的比较而不是给我们 UB?
这源于不精确的规范,此后已得到纠正。
在C++17中,这些比较被指定为:
要求:表达式
*x == *y
应格式正确,其结果应可转换为bool
.
Requires 是一个先决条件,因此不满足这些条件将是未定义的行为。但是有许多不同种类的“先决条件”——这是否意味着静态检查,这是否意味着如果条件不满足,则将运算符从重载集中删除,是否意味着实际的未定义行为?
在C++20中,这些被指定为:
要求:表达式
*x == *y
格式正确,其结果可转换为bool
.
这意味着如果不满足条件,则程序格式错误。基本上,授权是static_assert
(或等效的)。
所以是的,标准库有义务拒绝比较不存在或没有给你类似bool
. 这实际上永远不会给您未定义的行为(如果没有这样的运算符,实现会做什么,从 ? 读一点/dev/random
?)但现在它被更明确地指定了。
这些变化来自 Marshall Clow 题为“Mandating the Standard Library”的一系列论文,这篇论文特别来自P1460(感谢 Marshall!)。用于指定标准库的新术语来自 Walter Brown 的“Guidelines for Formulating Library Semantics Specifications”论文 ( P1369 )。