C ++ вектор массивов - PullRequest
28 голосов
/ 18 мая 2011

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

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> >’

Спасибо

Ответы [ 2 ]

24 голосов
/ 18 мая 2011

К сожалению, std::array не имеет конструктора списка инициализатора. Действительно, у него есть нет пользовательского конструктора вообще - эта «особенность» является остатком C ++ 03, где исключение всех пользовательских конструкторов было единственным способом включить инициализацию скобки в стиле C. Это ИМХО дефект текущего стандарта.

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

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

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

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

C (и, следовательно, 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?

4 голосов
/ 18 мая 2011

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

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

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

...