gpt4 book ai didi

C++1y/C++14 : Assignment to object outside its lifetime is not allowed in a constant expression?

转载 作者:IT老高 更新时间:2023-10-28 22:21:45 25 4
gpt4 key购买 nike

根据当前草案,以下 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;
}

Clang trunk(在撰写本文时)给出:

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 构造函数

我们可以在 draft standard 中找到它7.1.5 部分 constexpr 说明符 段落 3 说:

The definition of a constexpr function shall satisfy the following constraints:

并包括以下项目符号:

its function-body shall be = delete, = default, or a compound-statement that does not contain

其中包含此项目符号(强调我的):

a definition of a variable of non-literal type or of static or thread storage duration or for which no initialization is performed.

然后我们有以下示例:

constexpr int uninit() {
int a; // error: variable is uninitialized
return a;
}

关于x 的生命周期的提示似乎不是建立在draft standard 中的。 .据我所知,正确的原因应该是 object is not initialized

关于对象生命周期的标准草案中的相关引用将是 3.8 Object生命周期 段落 1 部分,它说:

The lifetime of an object is a runtime property of the object. An object is said to have non-trivial initialization if it is of a class or aggregate type and it or one of its members is initialized by a constructor other than a trivial default constructor. [ Note: initialization by a trivial copy/move constructor is non-trivial initialization. — end note ] The lifetime of an object of type T begins when:

  • storage with the proper alignment and size for type T is obtained, and
  • if the object has non-trivial initialization, its initialization is complete.

以防万一我遗漏了什么,我还使用 std::is_trivial 进行了检查:

std::cout <<  std::boolalpha << std::is_trivial<literal_array<int, 3>>::value << std::endl ;

true中预期的结果,.

更新

我提交了 bug report为此,回复包括以下声明:

[...]The problem is that we don't yet implement the implied rule that such a function can't be invoked in a constant expression.

关于C++1y/C++14 : Assignment to object outside its lifetime is not allowed in a constant expression?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21806154/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com