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

含非平凡析构成员的联合体能否拥有constexpr析构?编译器差异及方案问询

联合体含非平凡析构成员时的constexpr析构问题

问题说明

当联合体包含拥有非平凡析构函数的成员时,能否为该联合体声明constexpr析构函数?以下示例代码在GCC中可编译通过,但Clang拒绝编译:

struct Foo {
    int x, y;
    ~Foo() {} // 非平凡析构函数
};

union U {
    char dummy;
    Foo f;

    constexpr ~U() {} // 尝试声明constexpr析构函数
};

consteval void bar() {
    U u{}; // 在consteval函数中创建U对象
}

Clang的报错信息如下:

<source>:10:15: error: destructor cannot be declared constexpr because data member 'f' does not have a constexpr destructor
    constexpr ~U() {}
              ^
<source>:8:9: note: data member 'f' declared here
    Foo f;
    ^
<source>:13:16: error: consteval function never produces a constant expression [-Winvalid-constexpr]
consteval void bar() {
               ^
<source>:14:8: note: non-literal type 'U' cannot be used in a constant expression
    U u{};
       ^

标准符合性判断

Clang的处理符合C标准。根据C标准对constexpr析构函数的要求:类的所有非静态数据成员的析构函数必须是constexpr析构函数(或平凡析构函数,平凡析构默认满足constexpr要求)。此处Foo的析构函数是非平凡且非constexpr的,因此联合体U不能声明constexpr析构函数。GCC的处理属于放宽了标准约束,不符合规范。

修改方案

要在保留Foo非平凡析构函数的前提下,让bar函数中U u{}的定义合法,可采用以下两种方式:

方式1:将Foo的析构函数改为constexpr(允许微调Foo)

非平凡析构函数也可以是constexpr的,修改Foo的析构函数后,U的constexpr析构函数即可满足标准要求:

struct Foo {
    int x, y;
    constexpr ~Foo() {} // 非平凡但constexpr的析构函数
};

union U {
    char dummy;
    Foo f;

    constexpr ~U() {}
};

consteval void bar() {
    U u{};
    [[maybe_unused]] auto addr = &u.f.y; // 合法获取地址
}

方式2:不声明U的constexpr析构,改用编译期偏移量计算(严格不修改Foo)

若完全不能修改Foo,可通过offsetof宏直接计算Foo::y的偏移量,无需在consteval中创建U对象并访问成员:

#include <cstddef>

struct Foo {
    int x, y;
    ~Foo() {}
};

union U {
    char dummy;
    Foo f;
};

consteval ptrdiff_t get_y_offset() {
    return offsetof(Foo, y); // 编译期计算偏移量,等效于&u.f.y - &u
}

若必须创建U对象并直接获取u.f.y的地址,目前在严格遵循C++标准的前提下无法实现——因为U无法成为字面量类型(析构函数无法满足constexpr或平凡的要求),而consteval函数中只能使用字面量类型的变量。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 18:05:21