37

可能重复:
如何使用 initializer_list 初始化成员数组?

您可以使用初始化列表构造一个 std::array 就好了:

std::array<int, 3> a = {1, 2, 3};  // works fine

但是,当我尝试从std::initializer_list类中的数据成员或基对象构造它时,它不起作用:

#include <array>
#include <initializer_list>

template <typename T, std::size_t size, typename EnumT>
struct enum_addressable_array : public std::array<T, size>
{
    typedef std::array<T, size> base_t;
    typedef typename base_t::reference reference;
    typedef typename base_t::const_reference const_reference;
    typedef typename base_t::size_type size_type;

    enum_addressable_array(std::initializer_list<T> il) : base_t{il} {}

    reference operator[](EnumT n)
    {
        return base_t::operator[](static_cast<size_type>(n));
    }

    const_reference operator[](EnumT n) const
    {
        return base_t::operator[](static_cast<size_type>(n));
    }
};

enum class E {a, b, c};
enum_addressable_array<char, 3, E> ea = {'a', 'b', 'c'};

gcc 4.6 的错误:

test.cpp: In constructor 'enum_addressable_array<T, size, EnumT>::enum_addressable_array(std::initializer_list<T>) [with T = char, unsigned int size = 3u, EnumT = E]':
test.cpp:26:55:   instantiated from here
test.cpp:12:68: error: no matching function for call to 'std::array<char, 3u>::array(<brace-enclosed initializer list>)'
test.cpp:12:68: note: candidates are:
include/c++/4.6.1/array:60:12: note: std::array<char, 3u>::array()
include/c++/4.6.1/array:60:12: note:   candidate expects 0 arguments, 1 provided
include/c++/4.6.1/array:60:12: note: constexpr std::array<char, 3u>::array(const std::array<char, 3u>&)
include/c++/4.6.1/array:60:12: note:   no known conversion for argument 1 from 'std::initializer_list<char>' to 'const std::array<char, 3u>&'
include/c++/4.6.1/array:60:12: note: constexpr std::array<char, 3u>::array(std::array<char, 3u>&&)
include/c++/4.6.1/array:60:12: note:   no known conversion for argument 1 from 'std::initializer_list<char>' to 'std::array<char, 3u>&&'

我怎样才能让它工作,以便我的包装类可以使用初始化列表进行初始化,如下所示:

enum_addressable_array<char, 3, E> ea = {'a', 'b', 'c'};
4

3 回答 3

37

Anstd::array<>没有采用std::initializer_list<>(初始化列表构造函数)的构造函数,并且没有特殊的语言支持将 a 传递std::initializer_list<>给类的构造函数以使其可以工作。所以那失败了。

为了让它工作,你的派生类需要捕获所有元素,然后转发它们,一个构造函数模板:

template<typename ...E>
enum_addressable_array(E&&...e) : base_t{{std::forward<E>(e)...}} {}

请注意,{{...}}在这种情况下您需要,因为大括号省略(在您的情况下省略大括号)在该位置不起作用。它只允许在表单的声明中T t = { ... }。因为 anstd::array<>由嵌入原始数组的结构组成,所以需要两级大括号。不幸的是,我相信确切的聚合结构std::array<>是未指定的,因此您需要希望它适用于大多数实现。

于 2011-08-01T04:22:16.927 回答
32

由于 astd::array是一个包含聚合的结构(它本身不是聚合,并且没有采用 a 的构造函数std::initializer_list),因此您可以使用双括号语法使用初始化列表初始化结构内的底层聚合,如下所示:

std::array<int, 4> my_array = {{1, 2, 3, 4}};

请注意,这不是使用std::initializer_list... 这只是使用 C++ 初始化程序列表来初始化std::array.

于 2011-08-01T03:57:52.137 回答
10

Anstd::array没有采用std::initializer_list. 这是一件好事,因为初始化列表可以大于数组的固定大小。

您可以通过测试初始化​​器列表不大于数组的大小,然后将初始化器列表的元素复制到with的elems成员来初始化它。std::arraystd::copy

于 2011-08-01T03:09:14.727 回答