C++ 为什么使用结构初始化数组需要指定结构名称

C++ 为什么使用结构初始化数组需要指定结构名称,c++,aggregate,initializer-list,stdarray,C++,Aggregate,Initializer List,Stdarray,为什么这段代码会产生编译时错误 #include <array> #include <cstdint> #include <string_view> using namespace std::string_view_literals; enum class my_enum : std::size_t { first = 0, second, third, COUNT, }; struct my_enum_str_pair

为什么这段代码会产生编译时错误

#include <array>
#include <cstdint>
#include <string_view>

using namespace std::string_view_literals;

enum class my_enum : std::size_t {
    first = 0,
    second,
    third,

    COUNT,
};

struct my_enum_str_pair {
    std::string_view str;
    my_enum command;
};

constexpr 
std::array<my_enum_str_pair, static_cast<std::size_t>(my_enum::COUNT)> 
my_enum_str_pairs = {
    { "first"sv, my_enum::first },
    { "second"sv, my_enum::second }, // error: excess elements in struct initializer
    { "third"sv, my_enum::third },
};

#include

您缺少一对括号

constexpr
std::数组
my_enum_str_pairs=
{{
{“first”sv,my_enum::first},
{“second”sv,my_enum::second},//错误:结构初始值设定项中的元素过多
{“third”sv,my_enum::third}
}};

<代码> < P>行为由下面的引用C++ 17标准(111.1聚合)

解释 12大括号可以在初始值设定项列表中省略,如下所示。如果 初始值设定项列表以左大括号开始,随后是 以逗号分隔的初始化器子句列表初始化元素 属于亚集合体;再多一些是错误的 初始值设定项子句大于元素。但是,如果初始值设定项列表 对于子集合,不以左大括号开始,则仅足够 使用列表中的初始值设定项子句来初始化元素 亚集合体的稳定性;任何剩余的初始值设定项子句留待处理 初始化聚合的下一个元素,其中当前 子集料是一种元素

数组是一个包含另一个聚合的聚合

constexpr 
std::array<my_enum_str_pair, static_cast<std::size_t>(my_enum::COUNT)> 
my_enum_str_pairs = {
    { "first"sv, my_enum::first },
    { "second"sv, my_enum::second }, // error: excess elements in struct initializer
    { "third"sv, my_enum::third },
};
^^^

作为聚合
std::array
的内部子聚合(通常是数组)的初始值设定项。在这个列表之后,它遇到了第二个列表

{ "second"sv, my_enum::second }
但未找到
std::array
的另一个子对象。因此编译器发出一个错误

如果将这些列表用大括号括起来

constexpr 
std::array<my_enum_str_pair, static_cast<std::size_t>(my_enum::COUNT)> 
my_enum_str_pairs = {
{
    { "first"sv, my_enum::first },
    { "second"sv, my_enum::second }, // error: excess elements in struct initializer
    { "third"sv, my_enum::third },
}
};
在这种情况下,第一个打开的大括号如下

    Array<3> a = { { { 1 }, { 2 }, { 3 } } };
                  ^^^
初始值设定项列表不是以内部聚合Int a[N]的大括号开头的。它从铸造表达式开始

Int{ 1 }

因此,编译器将所有其他元素视为内部聚合Int a[N]的初始值设定项。因此,根据引用,大括号可能会被省略。

额外的一对大括号也有帮助:
my_enum_str_pairs={{{{“first”sv,my_enum::first},…}
我不记得为什么了,但是
std::array
有时需要这个额外的对。处理
std::array
初始化问题的常用方法是:继续添加更多的大括号,直到它工作为止,但为什么需要它?std::array包含一个内部数组。要初始化一个C数组,需要执行以下操作:int foo[]={};但是,该数组在std::array中,因此需要第二组括号。@S.M.我也这么认为。@S.M.我接受答案时不是这样的,我现在不想更改它。
constexpr 
std::array<my_enum_str_pair, static_cast<std::size_t>(my_enum::COUNT)> 
my_enum_str_pairs = {
                   ^^^^ 
    my_enum_str_pair{ "first"sv, my_enum::first },
    { "second"sv, my_enum::second },
    { "third"sv, my_enum::third },
};
#include <iostream>

struct Int
{
    Int( int x ) : x( x ) {}
    int x;
};

template <size_t N>
struct Array
{
    Int a[N];
};

int main() 
{
    Array<3> a = { { 1 }, { 2 }, { 3 } };

    return 0;
}
    Array<3> a = { { 1 }, { 2 }, { 3 } };
                  ^^^
#include <iostream>

struct Int
{
    Int( int x ) : x( x ) {}
    int x;
};

template <size_t N>
struct Array
{
    Int a[N];
};

int main() 
{
    Array<3> a = { { { 1 }, { 2 }, { 3 } } };

    return 0;
}
    Array<3> a = { { { 1 }, { 2 }, { 3 } } };
                  ^^^
#include <iostream>

struct Int
{
    Int( int x ) : x( x ) {}
    int x;
};

template <size_t N>
struct Array
{
    Int a[N];
};

int main() 
{
    Array<3> a = { Int{ 1 }, { 2 }, { 3 } };

    return 0;
}
Int{ 1 }