不能使用嵌套类的 constexpr 函数 [duplicate]

Can't use constexpr function of nested class [duplicate]

提问人:Newline 提问时间:9/24/2023 最后编辑:Jan SchultkeNewline 更新时间:9/25/2023 访问量:102

问:

struct Foo
{
    struct Bar
    {
        int data = 0;

        //constexpr Bar() = default; // Doesn't work either
        constexpr Bar() : data(0) {}
    };

    static constexpr Bar bar = {}; // ERROR
    //static constexpr Bar bar = {0}; // Works if the ctor from Bar is removed
};

Clang 和 GCC(std=c++20)说我尝试使用的构造函数未定义。但是如果我更改为 .我想了解使用“contexpr”有什么问题。constexprinline

C++ C++20 constexpr 静态成员

评论


答:

5赞 HolyBlackCat 9/25/2023 #1

编译器分两次分析一个类。第一遍处理成员变量和函数声明,第二遍处理函数,这允许您使用在该函数中的函数下声明的成员变量(或函数)。

当类嵌套时,第一次传递遍历整个最外层的类(包括所有嵌套类),然后同样地遍历整个最外层的类(包括嵌套类)。

显然,静态变量初始化发生在第一次传递期间。如果它是非 - (),那么看到一个构造函数声明就足够了。但如果是,则还需要查看构造函数定义(以立即计算值),但它在第一次传递期间不可用。constexprinlineconstexpr

当你摆脱构造函数并执行 ,这就是聚合初始化,它根本不使用构造函数,因此可以在第一次传递期间工作。= {0}

评论

1赞 user17732522 9/25/2023
由于完整的类上下文规则,该标准的当前措辞不一致。参见CWG第1255期
1赞 user17732522 9/25/2023
"而非 constexpr (inline) 静态变量初始化发生在第二遍中“:这并不是说这发生在第二阶段(即它不会发生在完整的类上下文中,并且所使用的所有内容的声明仍然需要出现在之前并且仍然必须完成)。相反,如果编译器认为构造函数(这是一个完整的类上下文)尚未定义用于目的,则初始化将根本不是一个常量表达式,这很好。您可以在运行时进行动态初始化。Barconstexprinline
0赞 HolyBlackCat 9/25/2023
@user17732522啊哈,谢谢。现在应该修复。