嵌套的隐式生命周期类型未在常量评估中创建:这是clang的一个错误吗?

编程语言 2026-07-10

这个问题是对 [将非平凡创建的数组设为constexpr] 和 [在std::allocator提供的存储中,在任何显式构造之前访问隐式寿命类型的对象] 的后续探讨,在那里我在寻找一种方法来创建一个 constexpr 数组,元素类型不是默认可构造的。

解决方案,受到第一个问题答案的提示,是使用 std::allocator::allocate,它是 constexpr

第二个问题涉及到该函数并不创建对象,而是创建对象的数组这一事实。不过,我在创建 std::array 的数组时,发现后者被隐式地创建为隐式寿命类型对象的子对象(即 std::array 的数组)的一部分。

测试它 时,代码被clang拒绝。

我可以把问题简化为这个mre:

#include <array>
#include <cstddef>
#include <iostream>
#include <memory>

template <typename T, std::size_t N>
constexpr T test() {
    std::allocator<std::array<T, N>> allocator{};
    auto* ptr = allocator.allocate(1);
    ptr->data()[3] = T{42}; // clang disapprove
    auto ret  = ptr->data()[3];
    allocator.deallocate(ptr,1);
    return ret;
}

int main() {
    constexpr std::size_t N = 50000;
    [[maybe_unused]] constexpr auto val = test<int, N>();
}

LIVE
clang拒绝常量求值,声称 std::array 不在其生存期内:

note: member call on object outside its lifetime is not allowed in a constant expression 10 | ptr->data()[3] = T{42};

gcc和 msvc对这段代码没有问题。

这是clang的 bug吗,还是我关于 std::array 的创建判断有误?

解决方案

Clang的判断是正确的。

std::allocator<T>::allocate(n) 启动了 T[N] 的生存期,但并未启动其元素的生存期。 ([allocator.members]/5)。

你似乎假设 T 作为隐式寿命类型也会启动元素的生存期,但这在编译时并不起作用。

在你之前的问题中,你提到 [intro.object]/13

Some operations are described as implicitly creating objects within a specified region of storage.

For each operation that is specified as implicitly creating objects, that operation implicitly creates and starts the lifetime of zero or more objects of implicit-lifetime types ([basic.types.general]) in its specified region of storage if doing so would result in the program having defined behavior.

allocate() 并未被描述为“隐式创建对象”,因此这条不适用于它。

allocate() 被说成在内部调用 operator new,该调用确实隐式创建对象,但不是在编译时[intro.object]/16

Except during constant evaluation, any implicit or explicit invocation of a function named operator new or operator new[] implicitly creates objects in the returned region of storage and returns a pointer to a suitable created object.

因此,std::array<...> 并非被隐式创建。

站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。

相关文章