问题
Possible Duplicate:
How do I initialize a member array with an initializer_list?
You can construct an std::array just fine with an initializer list:
std::array<int, 3> a = {1, 2, 3}; // works fine
However, when I try to construct it from an std::initializer_list
as a data member or base object in a class, it doesn't work:
#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'};
Errors with 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>&&'
How can I get it to work so that my wrapper class can be initialized with an initializer-list, as such:
enum_addressable_array<char, 3, E> ea = {'a', 'b', 'c'};
回答1:
An std::array<>
has no constructor that takes an std::initializer_list<>
(initializer list constructor) and there is no special language support for what it may mean to pass a std::initializer_list<>
to a class' constructors such that that may work. So that fails.
For it to work, your derived class needs to catch all elements and then forward them, a constructor template:
template<typename ...E>
enum_addressable_array(E&&...e) : base_t{{std::forward<E>(e)...}} {}
Note that you need {{...}}
in this case because brace elision (omitting braces like in your case) does not work at that place. It's only allowed in declarations of the form T t = { ... }
. Because an std::array<>
consists of a struct embedding a raw array, that will need two level of braces. Unfortunately, I believe that the exact aggregate structure of std::array<>
is unspecified, so you will need to hope that it works on most implementations.
回答2:
Since a std::array
is a structure that contains an aggregate (it is not an aggregate itself, and does not have a constructor that takes a std::initializer_list
), you can initialize the underlying aggregate inside the structure with an initializer list using a double-braces syntax like so:
std::array<int, 4> my_array = {{1, 2, 3, 4}};
Note that this is not using std::initializer_list
... this is simply using a C++ initializer list to initialize the publicly accessible array member of std::array
.
回答3:
An std::array
does not have a constructor that takes an std::initializer_list
. It's a good thing, because initializer lists can be bigger than the fixed-size of the array.
You can initialize it by testing that the initializer list is not larger than the size of the array and then copying the elements of initializer list to the elems
member of std::array
with std::copy
.
来源:https://stackoverflow.com/questions/24937814/how-to-delegate-initializer-list-constructor-call-to-a-c11-array-data-member