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

Неразумно ли игнорировать предупреждение gcc/clang -Wmissing-braces?

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

#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]

... и clang 3.1

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

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

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

  • Просто отключите его
  • Исправьте код, поэтому компилятор счастлив

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

4b9b3361

Ответ 1

-Wmissing-braces больше не будет включаться в GCC -Wall (для режима С++), начиная с 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
};

Однако IMHO, который уже достаточно хорошо обрабатывается -Wmissing-field-initializers, который не предупреждает о вашем исходном коде.

Ответ 2

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

array<T, N> a = { 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

Когда мы смотрим на подраздел 14882: 2011 8.5 [dcl.init], мы видим, что "список инициализаторов" необязательно может содержать "предложение инициализации", которое само может быть "бит-init-list". Таким образом, любой из способов должен быть правильным. Хотя, основываясь на спецификации, я лично думаю, что отдельные фигурные скобки не должны выводить предупреждение компилятора для списка инициализаторов std:: array, а двойные фигурные скобки - чрезмерное.

Ответ 3

При игнорировании предупреждения 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.