如何解决模板化的 constexpr 变量
我想确认这段代码是合法的(还是不合法的?)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
(MSVC 的 /std:c++17
)编译。
在 Godbolt 和我的本地机器上尝试过最新的编译器。
解决方法
constexpr
变量必须立即初始化。因此 MyConst
的模板需要初始化程序/定义。 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。
constexpr 说明符应仅应用于变量或变量模板的定义或函数或函数模板的声明。 consteval 说明符应仅应用于函数或函数模板的声明。使用 constexpr 或 consteval 说明符声明的函数或静态数据成员隐式是内联函数或变量。如果函数或函数模板的任何声明具有 constexpr 或 consteval 说明符,则其所有声明都应包含相同的说明符。
,问题是需要初始化 constexpr
。
C++14 标准,来自第 7.5.1 节第 9 段,
在对象声明中使用的 constexpr 说明符声明 对象作为常量。这样的对象应具有文字类型,并且应为 已初始化。
那么:
#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。
,这是DR 1712。
一方面,必须初始化 constexpr
变量,另一方面 template
在实例化之前不是“事物”,因此在此之前不一定需要初始值。
遗憾的是,该标准目前并未免除 constexpr
变量模板具有初始值的要求。所以从技术上讲,代码格式错误。
相应的 GCC 问题是 #68012,询问是否需要诊断。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。