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

构造variant期间观测其状态,哪个C++标准库实现符合规范?

问题分析结论

libc和MSVC的实现符合C标准要求,GCC 11的libstdc++实现不符合标准。

核心原因

你对valueless_by_exception()的语义和emplace的执行流程存在误解:

  • std::variant::emplace切换类型的标准执行顺序为:
    1. 销毁当前variant持有的旧值(示例中初始持有的std::monostate会被先销毁)
    2. 在variant的内部存储中构造新类型实例(即foo对象)
    3. 新对象构造完成后,variant标记为持有对应类型的有效值
  • 你在foo的构造函数中调用var.valueless_by_exception()时,正处于旧值已销毁、新对象未构造完成的过渡阶段,此时variant确实没有持有任何有效值。
  • C++标准明确规定valueless_by_exception()的返回规则为:当且仅当variant当前不持有任何值时返回true。你引用的标准条款仅说明「variant永久进入无值状态的唯一触发场景是emplace/赋值过程中抛出异常」,并没有禁止过渡阶段临时处于无值状态。
  • GCC libstdc++的实现属于非标准扩展,它在销毁旧值之前就先标记了新类型的状态,所以过渡阶段valueless_by_exception()也会返回false,这并不符合标准的语义要求。

测试代码

#include <variant>
#include <cassert>

struct foo {
  foo() noexcept;
  foo(const foo&) noexcept = default;
  foo(foo&&) noexcept = default;
  foo& operator=(const foo&) noexcept = default;
  foo& operator=(foo&&) noexcept = default;
};

std::variant<std::monostate, foo> var;  

foo::foo() noexcept {
    assert(!var.valueless_by_exception());
};

int main() {
    var.emplace<foo>();
}

内容的提问来源于stack exchange,提问作者Jean-Michaël Celerier

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.05 10:09:03