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

非结构类型constexpr参数的C++示例编译分歧:GCC与Clang谁合规?

Clang与GCC对非结构类型constexpr值编译的分歧分析

问题背景

以下是来自Ben Deane演讲的代码,GCC可正常编译,但Clang拒绝编译:

#define CX_VALUE(...) [] { 
    struct { 
        constexpr auto operator()() const noexcept { return __VA_ARGS__; } 
        using cx_value_tag = void; 
    } val; 
    return val; 
}()

template <typename T>
concept cx_value = requires { typename T::cx_value_tag; };

auto func(cx_value auto x) { 
    constexpr auto val = x();
    std::cout << "Constexpr value: " << val.val() << '\n';
}

class S {
    public:
    constexpr S(const int val) :  val_(val){}
    int val() const {
        return val_;
    }
    private:
    int val_;
};

int main() {
    constexpr S non_structural_value{420};
    func(CX_VALUE(non_structural_value));
}

核心分析

Clang的报错集中在func内的constexpr auto val = x();,认为该初始化不是合法的常量表达式,但根据C++标准,这行代码完全合规,原因如下:

  1. S是合法的字面类型
    根据C++标准对**字面类型(literal type)**的定义,S满足全部条件:

    • 拥有constexpr析构函数(默认生成的析构函数符合constexpr要求);
    • 拥有非拷贝/移动类别的constexpr构造函数;
    • 所有非静态数据成员(val_是int,属于标量字面类型)和基类均为字面类型。
  2. x()的调用是合法的常量表达式
    CX_VALUE宏生成的匿名结构体的operator()是constexpr函数,它返回non_structural_value的拷贝:

    • non_structural_value是main中合法初始化的constexpr变量;
    • 拷贝操作调用S的隐式constexpr拷贝构造函数——作为类成员函数,它有权访问private的val_,因此整个返回操作属于合法的常量表达式。
  3. constexpr变量初始化合规
    constexpr auto val = x();中,val的类型是字面类型S,初始化表达式x()是合法的常量表达式,完全符合C++标准对constexpr变量的要求。

结论

GCC的编译行为符合C++标准,Clang的报错属于实现bug——它错误地认为在常量表达式中拷贝非结构类型的constexpr对象时,无法访问其private成员,但实际上拷贝构造函数作为类成员拥有访问权限,整个操作是合规的。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.13 18:57:03