【问题标题】:Why do brace-enclosed initializer lists not work for std::array [duplicate]为什么大括号括起来的初始化列表不适用于 std::array [重复]
【发布时间】:2017-02-06 21:54:37
【问题描述】:

我想用对象列表初始化向量或数组。它适用于向量,但不适用于数组:

struct Widget
{
    string name;
    vector<int> list;
};

struct Object
{
    string name;
    vector<int> list;
    Object(string _name, vector<int> _list) : name(_name), list(_list) { }
};

int main()
{
    const vector<Widget> vw = {
        {"vw1", {1,2,3}},
        {"vw2", {1,2,3}} };
    const array<Widget,2> aw = {
        {"aw1", {1,2,3}},
        {"aw2", {1,2,3}} };
    const vector<Object> vo = {
        {"vo1", {1,2,3}},
        {"vo2", {1,2,3}} };
    const array<Object,2> ao = {
        {"ao1", {1,2,3}},
        {"ao2", {1,2,3}} };
    return 0;
}

来自clang的错误:

widget.cpp:36:9: error: excess elements in struct initializer
        {"aw2", {1,2,3}} };
        ^~~~~~~~~~~~~~~~
widget.cpp:41:10: error: no viable conversion from 'const char [4]' to 'Object'
        {"ao1", {1,2,3}},
         ^~~~~
widget.cpp:41:17: error: no matching constructor for initialization of 'Object'
        {"ao1", {1,2,3}},
                ^~~~~~~

向量和数组有什么区别,导致数组类型不支持这种语法?

【问题讨论】:

  • 我不是 100% 确定,但我相信这是聚合初始化和大括号括起来的初始化列表之间的奇怪交互。可以按照以下答案中的说明解决,但我不确定问题的具体原因是什么。更仔细地检查错误消息表明该数组正在“吸收”一个额外的大括号,无论如何,因为缺少更好的术语;注意它认为"ao1{1,2,3} 是两个不同的Objects,而不是同一个Object 的初始化列表的一部分。

标签: c++ c++11


【解决方案1】:

这是可行的解决方案 - 您需要为数组使用双括号。

int main()
{
    const vector<Widget> vw = {
        {"vw1", {1,2,3}},
        {"vw2", {1,2,3}} };
    const array<Widget,2> aw = {{
        {"aw1", {1,2,3}},
        {"aw2", {1,2,3}} }};
    const vector<Object> vo = {
        {"vo1", {1,2,3}},
        {"vo2", {1,2,3}} };
    const array<Object,2> ao = {{
        {"ao1", {1,2,3}},
        {"ao2", {1,2,3}} }};
    return 0;
}

为什么?

http://en.cppreference.com/w/cpp/container/array

std::array 是一个封装固定大小数组的容器。 此容器是一种聚合类型,其语义与将 C 样式数组 T[N] 作为其唯一非静态数据成员的结构相同。与 C 风格的数组不同,它不会自动衰减到 T*。作为一种聚合类型,它可以使用最多 N 个可转换为 T 的初始化器进行聚合初始化:std::array a = {1,2,3};。

理论实现(实际更复杂)

template <typename T, size_t size> 
struct array  
{
  T data[size]; 
}

所以第一个大括号是自行聚合初始化数组对象,第二个大括号是聚合初始化内部“传统 C 样式”数组。

【讨论】:

  • 这很有趣。这些是很多大括号......但是写的很有意义。链接的问题/答案也有帮助。谢谢!
【解决方案2】:

在您的示例中添加另一对大括号将使它们能够正常工作:

int main()
{
    const std::array<Widget,2> aw = {
        {
            {"aw1", {1, 2, 3}},
            {"aw2", {1, 2, 3}}
        }
    };

    const std::array<Object, 2> ao = {
        {
            {"ao1", {1, 2, 3} },
            {"ao2", {1, 2, 3} }
        }
    };

    cout << aw[0].name << " " << aw[1].list[1] << endl;
    cout << ao[0].name << " " << ao[1].list[1] << endl;

    return 0;
}

会给出输出:

aw1 2
ao1 2

由于std::array 本身没有构造函数,并且只是使用聚合初始化而不是列表初始化,因此需要额外的一对大括号。

在实现方面,std::array 包含一个内部项,即N 元素的真正底层数组。因此我们需要额外的大括号,所以我们用 one 元素初始化std::array(在您的示例中,这是一个由两个元素组成的数组)

【讨论】:

    猜你喜欢
    • 2012-11-21
    • 1970-01-01
    • 2021-07-14
    • 2016-12-11
    • 2012-10-02
    • 1970-01-01
    • 2021-12-31
    • 2013-06-03
    • 1970-01-01
    相关资源
    最近更新 更多