Отбросьте скобку в std :: array <std :: vector> - PullRequest
0 голосов
/ 14 ноября 2018

Я компилирую, используя g++ для C ++ 17. У меня есть следующее:

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

Я не понимаю, почему , если я удаляю двойные скобки для массива, он больше не работает.

std::array<std::vector<int>, 2> v = { {1,2}, {3,4} }; // Does not compile

Я понимаю, как работает std::array, и необходимость использования двойных скобок в целом, но, поскольку я компилирую для C ++ 17, я ожидал вступления в скобки.

Почему исключение скобок здесь не применимо?

Ответы [ 2 ]

0 голосов
/ 14 ноября 2018

std::array<std::vector<int>, 2> - это эффективно

struct array {
    std::vector<int> elems[2];
};

elems - это субагрегат, просто отлично.Проблема в том, что согласно правилам языка, если инициализатор начинается с {, всегда предполагается, что вы не выбрасываете скобки;вместо этого {1, 2} берется в качестве инициализатора всего подагрегата elems, пытаясь инициализировать свой первый элемент с 1, а второй элемент с 2 (это, очевидно, неверно - вы не можете преобразовать целое число вvector - но не влияет на интерпретацию), и {3, 4} считается инициализатором вещи после elems - и поскольку такой вещи нет, это еще одна ошибка.

Инициализация первойэлемент с чем-то, что не является braced-init-list достаточно для запуска скобки:

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

Обратите внимание, что с точки зрения спецификации библиотека не гарантирует инициализациюstd::array<T, N> из чего-либо, кроме std::array<T, N> или списка «до N элементов, типы которых могут быть преобразованы в T».Это, в частности, исключает braced-init-list s, потому что они не имеют типа, и фактически также запрещает «двойные скобки», потому что это просто особый случай наличия одного элемента, который является braced-init-список .

Это область, в которой нам, возможно, лучше было бы указать ее с помощью кода.Основные языковые правила не поддаются простой спецификации в словах, а детали реализации будут просачиваться - и уже сделали это.

0 голосов
/ 14 ноября 2018

Как Т.С. указал, что мое первоначальное толкование не было правдоподобным, исключение скобок разрешено, см. [dcl.init.aggr] p15 :

Брекеты могут быть исключены из списка инициализаторов следующим образом. Если список инициализаторов начинается с левой фигурной скобки, затем последующий разделенный запятыми список пунктов initializer инициализирует элементы субагрегата; ошибочно быть более инициализатор-предложения, чем элементы. Если, однако, список инициализатора для субагрегата не начинается с левой скобки, то достаточно только предложения инициализатора из списка взяты, чтобы инициализировать элементы субагрегата; любые оставшиеся предложения инициализатора оставляются инициализировать следующий элемент совокупности которых текущий субагрегат является элементом. ...

, но std::array в соответствии с array.overview :

Массив - это агрегат, который может быть инициализирован списком максимум с N элементами, типы которых могут быть преобразованы в T.

что не так у нас.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...