c++ - 作者基于 union 的可选 <bool> 实现在 P2641 中定义良好吗?

标签 c++ language-lawyer unions type-punning c++26

P2641r4: Checking if a union alternative is active ,作者提供了 optional<bool> 的实现作为一个激励性的例子,并声称这是格式良好的。

struct OptBool {
  union { bool b; char c; };

  OptBool() : c(2) { }
  OptBool(bool b) : b(b) { }

  auto has_value() const -> bool {
    return c != 2;
  }

  auto operator*() -> bool& {
    return b;
  }
};

但是,我并不相信。即has_value()看起来并不安全,因为如果 bool是活跃的 union 成员,则 c != 2访问非事件成员并执行 union 类型双关。据我所知,这在 C++ 中是不允许的。

作者解释说这是无法完成的,因为正在读取不活动的 union 成员,并提供了以下实现:

  constexpr auto has_value() const -> bool {
    if consteval {
      return std::is_within_lifetime(&b);
    } else {
      return c != 2;
    }
  }

作者这句话的意思是什么?这是否意味着您无法读取常量表达式中的非事件 union 成员,但否则会被允许? 该代码是否完全格式良好,或者是否依赖于允许在运行时进行 union 类型双关的编译器扩展?


注意:这是 Is the author's implementation of an optional<bool> well-defined in P2641? 的姐妹问题其中讨论了其他实现。

最佳答案

我假设 operator* 像往常一样有一个先决条件,即已使用 OptBool(bool b) 重载。当可选值为空时使用 operator* 显然是 UB,但也不是预期用途。

b 是事件成员时,访问 c 具有未定义的行为,因为它必须超出生命周期。

这里的目的是查看对象表示,这可以通过添加看似不必要的强制转换来实现:

return *reinterpret_cast<unsigned char*>(reinterpret_cast<OptBool*>(&c)) != 2;

内部转换将产生一个指向 OptBool 对象的指针,因为 OptBool 是标准布局,并且可以与 c 子对象进行指针互换.

然后,外部转换将生成一个指向具有表达式类型 unsigned char*OptBool 对象的指针。通过它进行访问并不违反别名。但是,目前尚未指定此访问应读取什么值。其目的是读取 OptBool 对象(以及 bool 或 char 对象)的对象表示形式的第一个字节,但是目前还没有指定会发生这种情况。有P1839试图解决这个问题。实际上,这是每个人都认为的行为,即使目前标准没有这么说,这是一个缺陷。

无论如何,实现当然假设了 bool 的特定实现,特别是它的大小、对齐方式和对象/值表示。

关于c++ - 作者基于 union 的可选 <bool> 实现在 P2641 中定义良好吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/77162785/

相关文章:

c++ - 在 C++ 中继承结构

c++ - 逐行 c - Linux ubuntu 中的 c++ 代码调试

c++ - 如何向线程传递消息

c++ - 为什么 map 不包括 out_of_range?

c++ - [class.union]/3中Note里的 "Absent default member initializers, ..."这句是什么意思?

c++ - C++ 和 C 中的 union 初始化

c++ - 我是否应该让一个成员函数成为虚拟的只是为了让一个类可测试?

c++ - 如何检查字符常量是否符合ASCII?

objective-c - 将 32 位结构传递给 32 位整数函数参数

c - 使用 union 处理错误