模板类类型的静态数据成员:constexpr 与 const constinit

问题描述 投票:0回答:1

我有课:

#include <array>

template<class T, std::size_t N>
    requires std::is_arithmetic_v<T> && (N >= 1)
class Vector
{
    static constexpr std::size_t Dimension = N;
    std::array<T, Dimension> Elements;

public:
    constexpr Vector() noexcept : Elements{} {}
    constexpr ~Vector() = default;
    static constexpr Vector ZeroVector{};
};

int main()
{
    Vector<float, 7> boo = Vector<float, 7>::ZeroVector;
}

上面的代码无法在具有 C++23 编译器标志的 MSVC 和 Clang (trunk) 的编译器资源管理器上编译,但它可以在具有 C++23 编译器标志的 GCC (trunk) 上编译。

Clang 给出以下错误:

<source>:13:29: error: constexpr variable cannot have non-literal type 'const Vector<float, 7>'
   13 |     static constexpr Vector ZeroVector{};
      |                             ^
<source>:18:28: note: in instantiation of template class 'Vector<float, 7>' requested here
   18 |     Vector<float, 7> boo = Vector<float, 7>::ZeroVector;
      |                            ^
<source>:13:29: note: incomplete type 'const Vector<float, 7>' is not a literal type
   13 |     static constexpr Vector ZeroVector{};
      |                             ^
<source>:5:7: note: definition of 'Vector<float, 7>' is not complete until the closing '}'
    5 | class Vector
      |       ^
1 error generated.
Compiler returned: 1

MSVC 给出以下错误:

<source>(13): error C2027: use of undefined type 'Vector<float,7>'
<source>(5): note: see declaration of 'Vector<float,7>'
<source>(13): note: the template instantiation context (the oldest one first) is
<source>(18): note: see reference to class template instantiation 'Vector<float,7>' being compiled
Compiler returned: 2

当我将

constexpr
更改为
const constinit
时,当定义移到类之外时,这会在所有三个主要编译器上进行编译,如下所示:
ZeroVector

那么为什么 
template<class T, size_t N> requires std::is_arithmetic_v<T> && (N >= 1) const constinit Vector<T, N> Vector<T, N>::ZeroVector{};

只能在 GCC 上编译,而

constexpr
可以在所有三个主要编译器上编译?
    

c++ constexpr static-variables c++23 constinit
1个回答
0
投票

来自 dcl.constexpr

对象声明中使用的 constexpr 说明符将对象声明为 const。 这样的对象应具有文字类型并应进行初始化。

在任何 constexpr 变量声明中,初始化的完整表达式应为常量表达式 ([expr.const])。 作为对象的 constexpr 变量以及绑定了 constexpr 引用的任何临时变量,应不断销毁。

(强调我的)

并且
const constinit

满足成为

文字类型

的条件。


因此 gcc 没有给出相同的诊断是正确的。
    


© www.soinside.com 2019 - 2024. All rights reserved.