模板化 constexpr 变量
Templated constexpr variable
我想确认此代码是否合法(或不合法?)C++17。
#include <iostream>
template<int N> inline constexpr float MyConst;
template<> inline constexpr float MyConst<1> = 1.1f;
template<> inline constexpr float MyConst<2> = 2.2f;
int main ()
{
std::cout << MyConst<1> << '\n';
return 0;
}
如果由 g++ 和 MSVC,
编译,我不会收到错误(并得到正确的输出)
但是Intel和clang报错:
test.cpp(3): error: missing initializer for constexpr variable
template<int N> inline constexpr float MyConst;
^
使用 -std=c++17
编译(/std:c++17
for MSVC)。
在 Godbolt 和我的本地机器上尝试了最新的编译器。
问题是 constexpr
需要初始化。
C++14 标准,来自第 7.5.1 节第 9 段,
A constexpr specifier used in an object declaration declares the
object as const. Such an object shall have literal type and shall be
initialized.
然后:
#include <iostream>
template<int N> inline constexpr float MyConst = 0.0f;
template<> inline constexpr float MyConst<1> = 1.1f;
template<> inline constexpr float MyConst<2> = 2.2f;
int main ()
{
std::cout << MyConst<1> << '\n';
return 0;
}
对 g++ 和 clang 都很好。
一个constexpr
变量必须立即初始化。因此 MyConst
的模板需要一个 initialiser/definition。 GCC 不要求在第一次出现时定义,这与规范背道而驰。如果您使用变量的非专业形式,例如MyConst<3>
you will get a similar error from GCC:
<source>: In instantiation of 'constexpr const float MyConst<3>':
<source>:10:18: required from here
<source>:3:40: error: uninitialized 'const MyConst<3>' [-fpermissive]
3 | template<int N> inline constexpr float MyConst;
| ^~~~~~~
ASM generation compiler returned: 1
<source>: In instantiation of 'constexpr const float MyConst<3>':
<source>:10:18: required from here
<source>:3:40: error: uninitialized 'const MyConst<3>' [-fpermissive]
3 | template<int N> inline constexpr float MyConst;
|
这可以通过为 MyConst 提供初始定义来解决,例如
// Use a "sensible default"
template<int N> inline constexpr float MyConst(0.0f);
// Provide a more general definition
template<int N> inline constexpr float MyConst = N*1.1f;
标准的相关部分,参见dcl.constexpr paragraph 1。
The constexpr specifier shall be applied only to the definition of a variable or variable template or the declaration of a function or function template. The consteval specifier shall be applied only to the declaration of a function or function template. A function or static data member declared with the constexpr or consteval specifier is implicitly an inline function or variable. If any declaration of a function or function template has a constexpr or consteval specifier, then all its declarations shall contain the same specifier.
这是DR 1712。
一方面,constexpr
变量必须初始化,另一方面,template
在实例化之前不是“事物”,因此在实例化之前不一定需要初始值那么
遗憾的是,该标准目前并未免除 constexpr
变量模板具有初始值的要求。所以从技术上讲,代码格式不正确。
对应的GCC问题是#68012,询问是否需要诊断。
我想确认此代码是否合法(或不合法?)C++17。
#include <iostream>
template<int N> inline constexpr float MyConst;
template<> inline constexpr float MyConst<1> = 1.1f;
template<> inline constexpr float MyConst<2> = 2.2f;
int main ()
{
std::cout << MyConst<1> << '\n';
return 0;
}
如果由 g++ 和 MSVC,
编译,我不会收到错误(并得到正确的输出)但是Intel和clang报错:
test.cpp(3): error: missing initializer for constexpr variable
template<int N> inline constexpr float MyConst;
^
使用 -std=c++17
编译(/std:c++17
for MSVC)。
在 Godbolt 和我的本地机器上尝试了最新的编译器。
问题是 constexpr
需要初始化。
C++14 标准,来自第 7.5.1 节第 9 段,
A constexpr specifier used in an object declaration declares the object as const. Such an object shall have literal type and shall be initialized.
然后:
#include <iostream>
template<int N> inline constexpr float MyConst = 0.0f;
template<> inline constexpr float MyConst<1> = 1.1f;
template<> inline constexpr float MyConst<2> = 2.2f;
int main ()
{
std::cout << MyConst<1> << '\n';
return 0;
}
对 g++ 和 clang 都很好。
一个constexpr
变量必须立即初始化。因此 MyConst
的模板需要一个 initialiser/definition。 GCC 不要求在第一次出现时定义,这与规范背道而驰。如果您使用变量的非专业形式,例如MyConst<3>
you will get a similar error from GCC:
<source>: In instantiation of 'constexpr const float MyConst<3>':
<source>:10:18: required from here
<source>:3:40: error: uninitialized 'const MyConst<3>' [-fpermissive]
3 | template<int N> inline constexpr float MyConst;
| ^~~~~~~
ASM generation compiler returned: 1
<source>: In instantiation of 'constexpr const float MyConst<3>':
<source>:10:18: required from here
<source>:3:40: error: uninitialized 'const MyConst<3>' [-fpermissive]
3 | template<int N> inline constexpr float MyConst;
|
这可以通过为 MyConst 提供初始定义来解决,例如
// Use a "sensible default"
template<int N> inline constexpr float MyConst(0.0f);
// Provide a more general definition
template<int N> inline constexpr float MyConst = N*1.1f;
标准的相关部分,参见dcl.constexpr paragraph 1。
The constexpr specifier shall be applied only to the definition of a variable or variable template or the declaration of a function or function template. The consteval specifier shall be applied only to the declaration of a function or function template. A function or static data member declared with the constexpr or consteval specifier is implicitly an inline function or variable. If any declaration of a function or function template has a constexpr or consteval specifier, then all its declarations shall contain the same specifier.
这是DR 1712。
一方面,constexpr
变量必须初始化,另一方面,template
在实例化之前不是“事物”,因此在实例化之前不一定需要初始值那么
遗憾的是,该标准目前并未免除 constexpr
变量模板具有初始值的要求。所以从技术上讲,代码格式不正确。
对应的GCC问题是#68012,询问是否需要诊断。