static constinit 成员变量是否与非类型模板参数相同?

Are static constinit member variables identical to non-type template parameters?

我有一个 N 维数组的 class 模板:

template<typename T, std::size_t... Shape>
class ndarray { ... };

此模板设计的一个结果是,如果您愿意,还有一个额外的 'implicit' 模板参数:std::size_t SizeShape 中所有参数的乘积。我一直在使用 C++17 折叠表达式 ((1 * ... * Shape)),如果它不依赖于 Shape,我通常会使用 Size,但我想知道是否添加以下内容'alias' 会导致编译后的程序集出现任何细微差异:

template<typename T, std::size_t... Shape>
class ndarray {
    static constinit std::size_t Size = (1 * ... * Shape);
    ...
};

有趣的是,ISO C++20 标准并没有像 constexprconsteval 那样说明 constinit 是否意味着 inline。我认为 constinit 的语义(尤其是与 constexpr 变量相关的语义)只有在变量也是 inline 时才真正有意义,但它在标准中的遗漏让我对这个结论持谨慎态度。

constinit只有一个语义:用于初始化变量的表达式必须是常量表达式。

就是这样。这就是它所做的全部:如果初始化表达式不是有效的常量表达式,它会导致编译错误。在其他方式中,这样的变量等同于没有constinit。事实上,该提案的早期版本将 constinit 作为属性而不是关键字,因为它实际上 没有任何作用。它只给出了变量初始化无效的编译错误。

对于这种情况,没有理由不使变量constexpr。您显然不打算更改变量,因此没有必要使变量可修改。

不,它们根本不一样,因为 constinit 没有生成变量 const。因此,Size 的初始化甚至 无效 。写作 constinit const 基本上等同于写作 constexpr,后者在语义上 等价于 常量 fold-expression。不能保证任何编译器都会以相同的方式对待它们,但在大多数常量表达式情况下,变化的空间不大。

constinit也不代表inline:不是标准“不说是否”,只是无话可说。由于将 constinitconstexpr 放在同一个变量上没有意义,因此不清楚您在该区域期望的语义。