标准要求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才出现,但空基类优化在标准库的其他部分被大量使用,所以如果需要的话,它肯定是可以做的。
1条答案
按热度按时间6mzjoqzu1#
是否空的
struct
与C++11中的双大括号初始化“问题”有关?std::array<T,N> myArray = {{ ... }};
在N3526之前,有一些场景需要双大括号来初始化
std::array
。如果std::array<T,0>
被实现为一个简单的空struct
,那么通过双大括号的初始化就不会被编译。所以,也许是为了确保所有的
std::array
示例化都可以用相同的语法初始化,他们添加了一个空的内部类?