标准是否要求 std::array<T, 0> 的行为就像没有尾随填充? [重复]

问题描述 投票:0回答:1
即使大小为零,标准也要求

std::array
必须明确定义,因此即使不允许
std::array<T, 0>
int[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 才出现,但空基类优化在标准库的其他部分中被广泛使用,因此如果需要的话,这绝对是可以完成的事情。

编辑:我的问题被标记为 C++ 编译器实际上符合零大小数组 SFINAE 规则吗? 的重复。这根本不是真的。我的问题是关于库功能

std::array
,即使大小为 0,该功能也由标准明确定义。链接的问题是关于数组的语言功能。

c++ c++11 language-lawyer stdarray object-layout
1个回答
0
投票

空的

struct
会不会与C++11中的双括号初始化“问题”有关?

std::array<T,N> myArray = {{ ... }};

N3526 之前,存在需要将大括号加倍才能列表初始化

std::array
的情况。如果
std::array<T,0>
已实现为简单的空
struct
,则无法编译通过双括号进行的初始化。

所以也许为了确保所有

std::array
实例化都可以使用相同的语法进行初始化,他们添加了一个空的内部类?

© www.soinside.com 2019 - 2024. All rights reserved.