Инициализация std::array с помощью std::initializer_list в списке инициализации конструктора

Рассмотрим следующий фрагмент кода:

struct foo {
  std::vector<int> v;
  foo(std::initializer_list<int> L) : v{L} {}
};

Приведенный выше код отлично компилируется и инициализирует v, как и ожидалось. Теперь рассмотрим следующий фрагмент кода:

struct bar {
  std::array<int, 3> a;
  bar(std::initializer_list<int> L) : a{L} {}
};

Приведенный выше фрагмент кода дает ошибку компиляции.

ошибка: невозможно преобразование из 'std::initializer_list' в 'int'

Поискав в Интернете, я обнаружил, что "правильный" способ инициализации члена std::array с помощью std::list_initializer заключается в использовании reinterpret_cast следующим образом:

bar(std::initializer_list<int> L) : a(reinterpret_cast<std::array<int, 3> const&>(*(L.begin()))) {}

Q:

Почему я могу инициализировать член std::vector с помощью std::initializer_list в списке инициализации конструктора, но не могу член std::array?

Является ли показанный выше обходной путь с reinterpret_cast правильным способом инициализации члена std::array с std::initializer_list?


person 101010    schedule 19.06.2015    source источник
comment
std::array не имеет никаких конструкторов, кроме того, что ему дает компилятор.   -  person chris    schedule 19.06.2015
comment
Приведение опасно, потому что список инициализаторов может содержать меньше элементов, чем массив.   -  person Cheers and hth. - Alf    schedule 19.06.2015


Ответы (3)


std::array был разработан (в библиотеке Boost) для поддержки синтаксиса инициализации фигурных скобок с С++ 03. Единственным способом сделать это в C++03 был тип POD (обычные старые данные), без конструкторов. Списки инициализаторов были введены в C++ 11 вместе с std::array, но std::array не был изменен по сравнению с версией Boost для использования списков инициализаторов. Итак, исторический.

Кстати, обратите внимание, что reinterpret_cast здесь опасен, потому что список инициализатора может содержать меньше элементов, чем array.

person Cheers and hth. - Alf    schedule 19.06.2015

std::array — это тонкая оболочка вокруг массива C++, смотрите как

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

Таким образом, у него нет конструктора, способного справиться с std::initializer_list, вы должны придерживаться vector или копировать элементы с чем-то другим (например, std::copy) в конструкторе.

person Jack    schedule 19.06.2015

foo(std::initializer_list<int> L) : v{L} {}

std::vector имеет конструктор, который принимает std::initializer_list в качестве входных данных. Таким образом, вы инициализируете сам вектор, а не какой-либо конкретный элемент std::vector.

bar(std::initializer_list<int> L) : a{L} {}

std::array не имеет конструктора, принимающего на вход std::initializer_list (на самом деле у него вообще нет конструкторов, его можно только инициализировать через агрегатная инициализация). Таким образом, вы пытаетесь инициализировать определенный элемент массива, поэтому компилятор жалуется, что не может преобразовать std::initializer_list в int.

person Remy Lebeau    schedule 19.06.2015