以下C ++ 14 / C ++ 1y程序是否根据当前草案格式错误?
#include <cstddef>
template<typename T, size_t n>
struct literal_array
{
T data[n];
};
template<typename T, size_t n, size_t m>
constexpr literal_array<T, n+m> operator+(literal_array<T, n> a,
literal_array<T, m> b)
{
literal_array<T, n+m> x;
for (size_t i = 0; i < n; i++)
x.data[i] = a.data[i];
for (size_t i = 0; i < m; i++)
x.data[n+i] = b.data[i];
return x;
}
int main()
{
constexpr literal_array<int, 3> a = { 1, 2, 3 };
constexpr literal_array<int, 2> b = { 4, 5 };
constexpr auto c = a + b;
}
lang主干(在撰写本文时)给出:
error: constexpr variable 'c' must be initialized by a constant expression
constexpr auto c = a + b;
^ ~~~~~
assignment to object outside its lifetime is not allowed in a constant expression
x.data[i] = a.data[i];
^
in call to 'operator+({{1, 2, 3}}, {{4, 5}})'
constexpr auto c = a + b;
^
什么是“在其生命周期之外分配对象”?x及其子对象的生命周期封装了该函数,那么它的作用是什么?
如果将定义更改为以下内容,则该程序格式不正确x
,因为您尚未初始化:
literal_array<T, n+m> x = {{0}};
clang
不再抱怨,它编译没有错误。另一个解决方案是创建constexpr构造器。
我们可以在标准草案7.1.5
的constexpr说明符第3段中找到该内容,该段内容为:
constexpr
函数的定义应满足以下约束:
并包括以下项目符号:
其功能主体应为
= delete
,= default
或不包含的复合语句
其中包含以下项目符号(重点是我的):
非文字类型或静态或线程存储持续时间的变量的定义,或者不对其执行初始化的变量。
稍后我们有以下示例:
constexpr int uninit() {
int a; // error: variable is uninitialized
return a;
}
标准草案x
似乎不存在关于的使用寿命的投诉。据我所知,正确的原因应该是与...相似的东西。object is not initialized
有关对象生存期的标准草案中的相关引用应为“对象生存3.8
期”第1段,其中指出:
对象的生存期是对象的运行时属性。如果对象属于类或聚合类型,并且其或其成员之一由除普通缺省构造函数之外的构造函数初始化,则称该对象具有非普通初始化。[注意:通过琐碎的复制/移动构造函数进行的初始化是非琐碎的初始化。—结束说明]类型的对象的生存期在以下情况下
T
开始:
- 获得具有适合类型的对齐方式和大小的存储
T
,并且- 如果对象具有非平凡的初始化,则其初始化完成。
万一我丢失了一些东西,我也使用std :: is_trivial进行了检查:
std::cout << std::boolalpha << std::is_trivial<literal_array<int, 3>>::value << std::endl ;
结果如预期true
。
更新
我为此提交了一个错误报告,答复中包含以下声明:
[...]问题是我们还没有实现不能在常量表达式中调用该函数的隐含规则。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句