c++ 标准是否要求std::array〈T,0>的行为就像没有尾部填充一样?

fdbelqdn  于 2022-11-19  发布在  其他
关注(0)|答案(1)|浏览(120)

标准要求std::array即使在大小为零时也是良好定义的,因此即使不允许int[0]std::array<T, 0>也是良好定义的(尽管GCC实现了对它的扩展)。
然而,在GCC、Clang和MSVC中,std::array<T, 0>不会被当作零大小的结构体来处理,也就是说,它不会像有尾部填充一样工作,因此[[no_unique_address]]和空基优化不能处理它。例如:

#include <array>

struct Tester {
    [[no_unique_address]] std::array<char, 0> arr;
    char c;
};

struct Tester2 : std::array<char, 0> {
    char c;
};

// true on GCC, Clang, and MSVC at least:
static_assert(sizeof(Tester) == 2);
static_assert(sizeof(Tester2) == 2);

这是令人惊讶的,因为它显然可以作为一个空结构实现。这是标准强制要求的吗?
注意:我已经查看了libstdc++的代码,它是这样工作的,因为std::array<char, 0>包含一个空结构体的示例,该结构体不是[[no_unique_address]],并且没有使用空基类优化,也就是说,它看起来像这样:

template <typename T>
struct array<T, 0> {
    struct {} empty; // no [[no_unique_address]]!
};

但这并不能解释为什么要这样设计它。尽管[[no_unique_address]]直到C++20才出现,但空基类优化在标准库的其他部分被大量使用,所以如果需要的话,它肯定是可以做的。

6mzjoqzu

6mzjoqzu1#

是否空的struct与C++11中的双大括号初始化“问题”有关?
std::array<T,N> myArray = {{ ... }};
N3526之前,有一些场景需要双大括号来初始化std::array。如果std::array<T,0>被实现为一个简单的空struct,那么通过双大括号的初始化就不会被编译。
所以,也许是为了确保所有的std::array示例化都可以用相同的语法初始化,他们添加了一个空的内部类?

相关问题