使用声明中的元素类型隐式初始化 std::array

Initialize std::array using element type from the declaration implicitly

本文关键字:初始化 std array 类型 声明 元素      更新时间:2023-10-16

在下面的代码中,我试图初始化数组(原始 C-classic 和 std::array (,尽量减少元素类型的使用,即 S

#include <array>
struct S { unsigned u; int i; };
auto std_array = std::array<S, 3>{
    S{0U, 0},
    S{1U, 1},
    S{2U, 2}
};
S raw_array[] = {
    {0U, 0},
    {1U, 1},
    {2U, 2}
}; 
/*  // compile error: excess elements in struct initializer
std::array<S,3> std_array_no_type = {
    {0U, 0},
    {1U, 1},
    {2U, 2}
}; 
*/
std::array<S,3> std_array_one_type_only = {
    S{0U, 0},
    {1U, 1},
    {2U, 2}
}; 
int main() {}

使用raw_array我只能指定一次S。但是尝试对std::array相同的方法不起作用(请参阅注释std_array_no_type(。我必须为每个或(这也是问题的一个有趣的部分(指定S类型,仅用于初始值设定项列表中的第一个元素(请参阅std_array_one_type_only(。

那么,有没有办法仅使用一次类型S定义初始化的std::array对象?如果没有,根据标准的哪条?为什么单个显式类型 S 允许编译std_array_one_type_only

关于第一个问题,

那么,有没有办法只使用一次类型S来定义初始化的std::array对象呢?

你可以添加另一对{},因为std::array实际上包含一个底层数组。

std::array<S,3> std_array_one_type_only = {{{0U, 0}, {1U, 1}, {2U, 2}}}; 
//                                        ^                           ^ for std::array
//                                         ^                         ^  for underlying array
//                                          ^     ^                     for the 1st element of underlying array
//                                                   ^     ^            for the 2nd element of underlying array
//                                                            ^     ^   for the 3rd element of underlying array

关于第二个问题,

为什么单个显式类型S允许编译std_array_one_type_only

在聚合初始化中,可以省略嵌套初始值设定项列表的大括号,

如果聚合初始化使用copy- (until C++14)列表初始化语法 (T a = {args..} or T a {args..} (since C++14)(,则可以省略(省略(嵌套初始值设定项列表周围的大括号,在这种情况下,根据需要使用任意数量的初始值设定项子句来初始化相应子聚合的每个成员或元素,并使用后续的初始值设定项子句初始化对象的以下成员。

鉴于

std::array<S,3> std_array_no_type = {{0U, 0}, {1U, 1}, {2U, 2}}; 
//                                  ^                         ^  for std::array
//                                   ^     ^                     for underlying array

第一个{0U, 0}将尝试用于初始化整个底层数组,然后导致错误,例如初始值设定项中的多余元素std::array因为它不包含任何进一步的子对象。

鉴于

std::array<S,3> std_array_no_type = {S{0U, 0}, {1U, 1}, {2U, 2}}; 
//                                  ^                          ^ for std::array
//                                    ^     ^                    for the 1st element of underlying array
//                                             ^     ^           for the 2nd element of underlying array
//                                                      ^     ^  for the 3rd element of underlying array

S{0U, 0}不能用于初始化底层数组(它不满足聚合初始化的样式(,那么它将用于初始化底层数组的第一个元素,即应用上面的大括号省略规则,然后使用以下{1U, 1}{2U, 2}来初始化底层数组的以下成员。