You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

P2641中基于union的optional<bool>实现及改进版是否合规?

关于P2641r4中optional<bool>实现的标准合规性疑问

问题背景

在C++提案《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;
  }
};

但存在疑问:当bool是union的活跃成员时,has_value()中访问非活跃成员c属于union类型双关,这在C++标准中是不被允许的。

作者随后给出改进实现:

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

需要明确两个问题:

  • 作者的意图是不是常量表达式中不能读取union非活跃成员,但运行时允许?
  • 改进后的代码是否完全符合标准,还是依赖编译器扩展?

解答

1. 作者的核心意图

是的,作者的思路就是针对常量表达式和运行时两种场景做差异化处理:

  • 常量表达式语境:C++标准对常量表达式的约束非常严格,访问union的非活跃成员属于未定义行为,因此必须用std::is_within_lifetime(&b)(P2641提案引入的新工具,用于检测union成员是否处于活跃状态)来合法判断。
  • 运行时语境:作者默认了主流编译器在运行时对union类型双关的宽松处理——虽然C++标准本身不允许跨活跃成员的访问,但GCC、Clang、MSVC等主流编译器都提供了相关扩展支持,实际运行中不会出现问题。

2. 改进后代码的标准合规性

改进后的代码并非完全符合标准:

  • 常量表达式分支(if consteval块)是合规的:std::is_within_lifetime正是P2641提案要引入的标准工具,用于合法检测union成员的活跃状态,这部分完全符合提案通过后的标准要求。
  • 运行时分支(else块)依然依赖编译器扩展:C++标准始终禁止访问union的非活跃成员,哪怕是在运行时。作者这里是利用了主流编译器的实际行为——它们通常允许这种类型双关操作,前提是成员的内存布局兼容(bool和char的大小通常相同,内存布局一致)。

简言之,改进版在常量表达式场景下符合标准,运行时场景则依赖编译器的非标准扩展。


内容的提问来源于stack exchange,提问作者Jan Schultke

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.10 10:52:54