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

使用std::construct_at复制值切换union活跃成员是否合规?

能否通过std::construct_at复制原活跃成员的值来切换union的活跃成员?

以下是最简示例代码:

#include <memory>

constexpr int f() {
    union U {
        char x{0};
        int y;
    } u;
    std::construct_at(&u.y, u.x);
    return u.y;
}

static_assert( f() == 0 );

该代码可被GCC和MSVC接受,但会被Clang拒绝,报错信息如下:

/opt/compiler-explorer/clang-19.1.0/bin/../include/c++/v1/__memory/construct_at.h:41:50:
note: read of member 'x' of union with active member 'y' is not allowed in a constant expression
41 | return ::new (std::__voidify(*__location)) _Tp(std::forward<_Args>(__args)...);

编译器正确性分析

根据C++标准规则:

  • union的活跃成员是最后被初始化或构造的成员。示例中u的初始活跃成员是x(因为x带有默认初始化器{0})。
  • std::construct_at(&u.y, u.x)的执行流程中,参数u.x的求值发生在u.y的构造操作之前——此时x仍然是union的活跃成员,读取x完全合法。
  • 当placement new完成u.y的构造后,y才会成为新的活跃成员,后续读取u.y也符合规则。

Clang的错误在于错误判定:在参数u.x求值时,y已经是活跃成员。这不符合C++标准中“参数求值先于函数/构造操作执行”的顺序规则。因此GCC和MSVC的实现是正确的,Clang的拒绝行为有误。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.16 07:57:07