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

g++-12编译constexpr虚析构函数代码报析构函数定义前使用错误

问题现象

使用g++-12编译如下测试代码时,会触发clang++-13不会报出的编译错误:

struct A {
    constexpr virtual ~A() = default;
    constexpr A() = default;
};

struct B : public A {
    constexpr ~B() = default;
    constexpr B() = default;
};

constexpr int demo(){
    B *b = new B();
    delete b;
    return 2;
}

int main(){
    constexpr int demod = demo();
    return demod;
}

上述代码在clang++-13环境下可正常编译通过,g++-12抛出的错误信息如下:

minimize-error.cpp: In function ‘int main()’:
minimize-error.cpp:18:31:   in ‘constexpr’ expansion of ‘demo()’
minimize-error.cpp:13:12: error: ‘virtual constexpr B::~B()’ used before its definition
   13 |     delete b;
      |

实际测试验证:移除demod变量的constexpr限定后,代码可在g++环境下正常编译运行。

问题原因

该错误是g++-12版本的C20 constexpr特性实现缺陷导致,测试代码本身符合C20标准规范。
按照C20标准规则,类内通过=default声明的constexpr虚析构,在constexpr上下文中被调用(本例中为delete b触发多态虚析构调用)时,编译器应当自动隐式生成析构函数的定义,供编译期求值使用。g-12处理多态虚析构的constexpr调用逻辑存在问题,错误延后了默认析构的隐式定义生成时机,在调用点做定义存在性检查时还未获取到析构函数的有效定义,因此抛出“使用前未定义”的错误。clang++-13对该部分逻辑的实现符合标准要求,因此不会触发报错。
移除demod的constexpr限定后,demo()的求值流程从编译期转移到运行时,不会触发编译期常量求值阶段的定义存在性校验,析构函数的定义会在后续编译、链接阶段正常生成,因此代码可以正常编译运行。

解决方法

可根据实际场景选择以下任意一种方案修复:

  • 升级g版本:g-13及以上正式版本已经修复了该constexpr虚析构的实现bug,升级后原代码无需任何修改即可正常编译通过。
  • 若必须使用g++-12版本,可手动将派生类B的析构函数改为类外默认定义,提前让编译器在编译期求值前获取到析构的定义,修改示例如下:
struct B : public A {
    constexpr ~B();
    constexpr B() = default;
};
constexpr B::~B() = default;
  • 若不需要在编译期对demo()的结果做常量求值,直接移除demod变量的constexpr限定,将逻辑求值放到运行时,即可绕过该编译错误。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 02:57:06