Как построить объект std:: array с именем инициализатора?
Возможный дубликат:
Как инициализировать массив-член с параметром initializer_list?
Вы можете построить массив std:: отлично, с помощью списка инициализаторов:
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'};
Ответы
Ответ 1
An std::array<>
не имеет конструктора, который принимает std::initializer_list<>
(конструктор списка инициализаторов), и нет специальной поддержки языка для того, что может означать передать конструкторы std::initializer_list<>
для класса, которые могут работать. Так что это не удается.
Чтобы он работал, ваш производный класс должен улавливать все элементы, а затем пересылать их, шаблон конструктора:
template<typename ...E>
enum_addressable_array(E&&...e) : base_t{{std::forward<E>(e)...}} {}
Обратите внимание, что в этом случае вам понадобится {{...}}
, потому что в этом месте не работает фигурная скобка (исключая фигурные скобки, как в вашем случае). Это разрешено только в объявлениях формы T t = { ... }
. Поскольку std::array<>
состоит из структурного вложения необработанного массива, для которого потребуется два уровня брекетов. К сожалению, я считаю, что точная совокупная структура std::array<>
не определена, поэтому вам нужно надеяться, что она будет работать на большинстве реализаций.
Ответ 2
Так как a std::array
- это структура, которая содержит агрегат (он не является агрегатом и не имеет конструктора, который принимает std::initializer_list
), вы можете инициализировать базовый агрегат внутри структуры с помощью списка инициализаторов используя синтаксис с двумя скобками, например:
std::array<int, 4> my_array = {{1, 2, 3, 4}};
Обратите внимание, что это не используется std::initializer_list
... это просто использование списка инициализаторов С++ для инициализации публично доступного элемента массива std::array
.
Ответ 3
An std::array
не имеет конструктора, который принимает std::initializer_list
. Это хорошо, потому что списки инициализаторов могут быть больше, чем фиксированный размер массива.
Вы можете инициализировать его, проверив, что список инициализаторов не больше размера массива, а затем копирует элементы списка инициализаторов в elems
член std::array
с помощью std::copy
.