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