Последняя версия Visual Studio 2019, компилирующая следующий код с переключателем командной строки /Wall (который включает все предупреждения):

struct A{};

void f( const std::array<A, 2> & ) {}

int main() {
    A x, y;
    f( { x, y } );
}

Выводит предупреждение:

warning C5246: 'std::array<A,2>::_Elems': the initialization of a subobject should be wrapped in braces

Однако и GCC, и Clang принимают код с самой педантичной проверкой ошибок, демонстрация: https: //gcc.godbolt .org / z / Ps6K6jK1G

Действительно, все компиляторы принимают вызов f( { { x, y } } );

Прав ли MSVC, предлагая более простую форму без дополнительных скобок?

1
Fedor 26 Ноя 2021 в 19:04

2 ответа

Лучший ответ

Visual Studio 2019 имеет дефект CWG # 1270 и предлагает старое поведение инициализации.

std::array определяется как агрегат, содержащий другой агрегат.

Стандарт C ++ 17 (агрегаты 11.6.1)

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

Вы можете представить std::array<A, 2> как

struct Array {
    A sub[2];
};

Согласно цитате Array a {{x, y}} является правильным, но устаревшим, внутренние фигурные скобки являются совокупным инициализация вложенного массива.

Полезный поток Почему поведение C ++ initializer_list для std :: vector и std :: array разные?.

2
S.M. 26 Ноя 2021 в 19:37

Я считаю, что Clang и GCC теперь подавляют эту ошибку по умолчанию, поэтому предупреждение не раскрывает детали реализации. С учетом сказанного, VS раньше не выдавал мне ошибки при использовании C ++ 11, а Clang - (так что, похоже, они перевернули эту проблему). Вся документация предполагает, что двойные фигурные скобки являются наиболее подходящими; возможно, имеет смысл добавить их в соответствии с отраслевыми стандартами кодирования.

0
Max Dylan 26 Ноя 2021 в 19:25