Разумно ли игнорировать gcc / clang’s -Wmissing-braces & quot; предупреждение?

Рассмотрим следующую программу:

#include <array>

int main()
{
std::array<int, 1> x = { 0 }; // warning!
x = { { 0 } }; // no warning
return 0;
}

Первая инициализация приводит к предупреждениям на gcc 4.7.2 …

main.cpp:5:22: warning: unused variable ‘x’ [-Wunused-variable]

… и лязг 3.1

main.cpp:5:28: warning: suggest braces around initialization of subobject [-Wmissing-braces]
std::array<int, 1> x = { 0 };

Что касается стандарта, не должно быть никакой разницы между двойными или одинарными фигурными скобками, по крайней мере, в этом примере.

Есть два способа справиться с предупреждением:

  1. Просто выключи
  2. Исправьте код, чтобы компилятор был доволен

Что вы предлагаете? ИМХО, двойное вьющееся выражение выглядит несколько некрасиво. С другой стороны, предупреждение может обнаружить реальные проблемы в более сложных примерах. Вы знаете пример, где предупреждение помогло бы вам?

45

Решение

-Wmissing-braces больше не будет включен в GCC -Wall (для режима C ++), начиная с 4.8, именно по той причине, которую вы описываете. Для текущих версий GCC, либо отключите, либо игнорируйте предупреждение, ваш код написан так, как должен быть.

Предупреждение, вероятно, предназначено для покрытия кода, такого как

struct A { int a; int b; };
struct B { A a; int b; };
B b = {
1,
2 // initialises b.a.b, not b.b
};

Однако, ИМХО, это уже достаточно хорошо -Wmissing-field-initializers, который не предупреждает о вашем исходном коде.

45

Другие решения

Я получаю то же предупреждение в Xcode 6.1.1 (текущая версия от 9 марта 2015 года). Когда я добавляю дополнительные скобки вокруг каждого подобъекта, я получаю ошибку. Когда я добавляю дополнительный набор скобок по всему списку инициализации, предупреждение исчезает. Согласно стандартной спецификации 14882: 2011 23.3.2.1 [array.overview] подраздел 2 прямо заявляет

array<T, N> a = { initializer-list };

где initializer-list — разделенный запятыми список до N элементов
чьи типы могут быть преобразованы в T

результат кода в Xcode 6.1.1 (ниже)

array<int, 2> key1 = {1, 2}; // warning: suggest braces around initialization of subobject

array<int, 2> key2 = { {1}, {2} }; // error: no viable overload =

array<int, 2> key3 = array<int, 2> { {1}, {2} }; // error: excess elements in struct initializer

array<int, 2> key4 = { {1, 2} }; // no warning and no error

Если мы посмотрим на подраздел 1 14882: 2011 8.5 [dcl.init], то увидим, что «initializer-list» может дополнительно содержать «initializer-clause», который сам по себе может быть «braced-init-list». Так что в любом случае должно быть правильно. Хотя, исходя из спецификации, я лично считаю, что одиночные скобки не должны выводить предупреждение компилятора для списка инициализаторов std :: array, а двойные скобки — это перебор.

7

При игнорировании предупреждения Clang с -Wno-missing-bracesЯ бы порекомендовал включить -Wmissing-field-initializers (или использовать -Wextra, который также включает это). В противном случае вы пропустите полезное предупреждение, как в этом примере:

#include <cstdio>

struct A
{
int i;
int arr[2];
int j;
};

void print(const A& a)
{
printf("i=%d, arr={%d,%d}, j=%d\n", a.i, a.arr[0], a.arr[1], a.j);
}

int main() {
A a = {1, 2, 3}; // this is the critical line
print(a); // output: i=1, arr={2,3}, j=0

A b = {1, {2}, 3};
print(b); // output: i=1, arr={2,0}, j=3

A c = {1, {2,0}, 3};
print(c); // output: i=1, arr={2,0}, j=3

return 0;
}
$ clang++ -Wall example.cpp
example.cpp:16:13: warning: suggest braces around initialization of
subobject [-Wmissing-braces]
A a = {1, 2, 3};
^~~~
{   }
1 warning generated.

$ clang++ -Wall -Wno-missing-braces example.cpp
(no warnings)

$ clang++ -Wall -Wno-missing-braces -Wmissing-field-initializers example.cpp
example.cpp:16:17: warning: missing field 'j' initializer
[-Wmissing-field-initializers]
A a = {1, 2, 3};
^
1 warning generated.

$ clang++ --version
clang version 3.8.1 (tags/RELEASE_381/final)

Для сравнения, вот что делает GCC:

$ g++ -Wall -Wextra example.cpp
(no warning)

$ g++ -Wall -Wmissing-field-initializers example.cpp
example.cpp: In function ‘int main()’
example.cpp:16:17: warning: missing initializer for member ‘A::j’ [-Wmissing-field-initializers]
A a = {1, 2, 3};
^

В итоге:

  • Для Clang я бы порекомендовал -Wno-missing-braces -Wmissing-field-initializers заставить замолчать предупреждение без потери других полезных предупреждений
  • GCC не жалуется в оригинале std::array<int, 1> x = { 0 }; Например, нет необходимости отключать какие-либо предупреждения. Тем не менее, я бы рекомендовал включить -Wmissing-field-initializers (или использовать -Wextra), так как он не включен -Wall,
3

Clang 6.0 подавляет предупреждение о пропавших скобках. Журнал SVN говорит:

Подавлять -Wmissing-braces предупреждение, когда агрегат-инициализирует структуру с одним полем, которое само является агрегатом. В C ++ такая инициализация типов std :: array гарантированно работает по стандарту, полностью идиоматична, и «предложенная» альтернатива
Clang был технически недействительным.

Так что я бы опустить скобки и отключить -Wmissing-braces для Clang до 6.0, если это необходимо поддерживать.

2
По вопросам рекламы [email protected]