Подтвердить что ты не робот

С++ вектор массивов

Почему это работает:

std::pair<int, int> p = {1,2};
std::vector<std::pair<int, int>> vp = { {1,2}, {3,4} };

Но это не так?

std::array<int, 2> a = {1,2}; // still ok
std::vector<std::array<int, 2>> va = { {1,2}, {3,4} };

Используя g++ 4.5.1 с -std=c++0x, вторая строка не работает:

ошибка: не удалось преобразовать ‘{{1, 2}, {3, 4}}’ в ‘std::vector<std::array<int, 2u> >’

Спасибо

4b9b3361

Ответ 1

К сожалению, std::array не имеет конструктора списка инициализаторов. В самом деле, у него нет никакого определяемого пользователем конструктора - эта "функция" осталась на С++ 03, где исключение всех определяемых пользователем конструкторов было единственным способом включить инициализацию скобки C-стиля. Это IMHO - дефект в текущем стандарте.

Итак, почему в этом случае не работает встроенная инициализация скобок? Посмотрим, как выглядит std::array под капотом:

template <typename T, int i> struct array {
    T data[i];
    // ...
}

Итак, не означает ли это, что нам нужно использовать двойные фигурные скобки в инициализаторе (одна пара для array, еще одна пара для члена data?

std::array<int, 2> a = { {1, 2} };

C (и, следовательно, С++) имеет специальное правило о выравнивании фигурной скобки, допускающее упущение внутренних скобок, если не существует двусмысленности. array использует эту функцию, позволяя нам писать

std::array<int, 2> a = { 1, 2 };

Так почему же не работает пример в исходном сообщении? Поскольку выравнивание фигурных скобок разрешено только в контексте инициализации агрегатного типа C, а не в случае чего-то более сложного, например, определяемого пользователем конструктора списка инициализаторов.

Следующее должно работать, однако, как уродливое, как это:

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

Тот факт, что это не так, по крайней мере на gcc 4.5 и gcc 4.6, мне кажется, указывает на ошибку компилятора. Я не совсем уверен в этом.

Этот вопрос несколько уместен: Как инициализировать массив-член с помощью initializer_list?

Ответ 2

Это работает:

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

Копая глубже, похоже, что std:: pair имеет конструктор, который принимает список инициализаторов, но std:: array не делает:

std::pair<int, int> p ({1,2}) ;  // OK
std::array<int, 2> a ({1,2}) ;   // Invalid

Но теперь я не в своей глубине.