提问者:小点点

在哪些情况下,std::optional operator==会导致未定义的行为?


cppreference对std::optional的混合(可选和一些其他非可选类型)比较运算符有以下描述:

将opt与值进行比较。 只有当opt包含值时,才会比较值(使用T的相应运算符)。 否则,opt被认为小于价值。 如果*opt和value之间对应的双向比较表达式格式不正确,或者它的结果不能转换为bool,则行为是未定义的。

这里让我困惑的是:

>

  • 这种格式不正确的比较有哪些例子?

    为什么编译器/STL不直接拒绝无效的比较,而是给我们UB呢?


  • 共1个答案

    匿名用户

    这是由于规格不精确所致,但后来已加以纠正。

    在C++17中,这些比较被指定为:

    要求:表达式*x==*y必须格式正确,其结果必须可转换为bool

    Requires是一个前提条件,因此不满足这些条件将是未定义的行为。 但是有许多不同种类的“前提条件”--这是否意味着静态检查,这是否意味着如果条件不满足,从重载集中移除运算符,这是否意味着实际的未定义行为?

    在C++20中,它们被指定为:

    授权:表达式*x==*y格式良好,其结果可转换为bool

    这意味着如果不满足这些条件,程序的格式就不正确。 基本上,任务是static_assert(或等效)。

    因此,是的,标准库有义务拒绝比较不存在或没有提供类似bool的类型。 这实际上不会给您提供未定义的行为(如果一个实现没有这样的运算符,那么它会做什么,从/dev/random中读取一点信息?) 但现在它被更明确地规定了。

    这些变化来自于Marshall Clow的一系列论文,题目是《标准库的授权》,这篇文章特别来自P1460(谢谢,Marshall!)。 规定标准库的新术语来自Walter Brown的“制定库语义规范的指南”论文(P1369)。