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

constexpr函数是否允许返回非字面量类型?

问题复现代码
struct Outer
{
    explicit constexpr Outer(int ii) : n(ii) {}
    explicit constexpr Outer(double dd) : n(dd) {}

    explicit constexpr Outer(double*) : Outer(3.1415926) {}
    explicit constexpr Outer(int*): Outer(42) {}

    template <typename R>
    static
    constexpr
    Outer meow(R* r = nullptr) { return Outer(r); }

    int    as_i() const { return n.i; }
    double as_d() const { return n.d; }

    union Inner
    {
        int i;
        double d;

        constexpr Inner(int ii) : i(ii) {}
        constexpr Inner(double dd) : d(dd) {}
        ~Inner () {}; // 非平凡析构函数

    };

    Inner n;
};

//#include <type_traits>
//static_assert(std::is_literal_type_v<Outer>); // GCC和Clang均会判定该断言失败

int main(int argc, char**)
{
    auto const o = Outer::meow(&argc);
    return o.as_i();
}
编译行为差异
  • 上述代码可被GCC 12.1正常编译,但会被Clang 14.0.0拒绝。
  • 在线编译验证地址:Godbolt在线验证
Clang编译报错输出

从C++语法规则判定,Clang的行为是正确的,对应报错内容如下:

<source>:12:11: error: constexpr function's return type 'Outer' is not a literal type
    Outer meow(R* r = nullptr) { return Outer(r); }
          ^
<source>:28:11: note: 'Outer' is not literal because it has data member 'n' of non-literal type 'Outer::Inner'
    Inner n;
          ^
<source>:36:24: error: no matching function for call to 'meow'
    auto const o = Outer::meow(&argc);
                   ^~~~~~~~~~~
<source>:12:11: note: candidate template ignored: substitution failure [with R = int]
    Outer meow(R* r = nullptr) { return Outer(r); }
          ^
核心疑问

即便变量o仅被const修饰、并未声明为constexpr,上述写法难道不应当报错吗?meow作为constexpr函数返回非字面量类型的行为本身就不符合语法规则。

补充测试现象

如果将o声明为constexpr变量,GCC也会抛出错误,提示Outer类型存在非平凡析构函数。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.30 15:06:09