Search code examples
c++gcc-warning

Are curly braces really required around initialization?


According to GCC 4.6.3 (Ubuntu/Linaro 4.6.3-1ubuntu5) I'm missing a curly brace in the array initialization in the following code:

#include <iostream>
#include <boost/array.hpp>
#include <array>

int main(){
  int                   plain[]   = {1,2,3,4,5};
  std::array  <int, 5>  std_arr   = {1,2,3,4,5}; // warning, see below
  boost::array<int, 5>  boost_arr = {1,2,3,4,5}; // warning, see below
  std::cout << plain[0] << std_arr[1] << boost_arr[2] << std::endl;
}
> g++ test.cc -Wall -Wextra -pedantic --std=c++0x                                                                                  
test.cc: in function »int main()«:
test.cc:7:47: warning: curly braces missing around initialization for »std::array::value_type [5] {aka int [5]}« [-Wmissing-braces]
test.cc:8:47: warning: curly braces missing around initialization for »int [5]« [-Wmissing-braces]

Apparently (GCC missing braces around initializer) this is a bug in GCC, even in a slightly different context. The answers differ from "file a bug report" to "just disable the warning".

However, in the context of std::array or boost::array, is this warning superfluous, or am I missing something important?

(I will probably add the additional braces instead of disabling the warning, but I'm curious about the implications)


Solution

  • I think this is already answered here.

    std::array is funny. It is defined basically like this:

    template struct std::array { T a[size]; };

    It is a struct which contains an array. It does not have a constructor that takes an initializer list. But std::array is an aggregate by the rules of C++11, and therefore it can be created by aggregate initialization. To aggregate initialize the array inside the struct, you need a second set of curly braces:

    std::array strings = {{ "a", "b" }};

    Note that the standard does suggest that the extra braces can be elided in this case. So it likely is a GCC bug.

    I believe it might be related to this defect, which has been linked in several questions.

    Here's an answer regarding it:

    However, these extra braces may only be elided "in a declaration of the form T x = { a };" (C++11 §8.5.1/11), that is, when the old style = is used . This rule allowing brace elision does not apply for direct list initialization. A footnote here reads: "Braces cannot be elided in other uses of list-initialization."

    There is a defect report concerning this restriction: CWG defect #1270. If the proposed resolution is adopted, brace elision will be allowed for other forms of list initialization, ...

    I noticed that the error does not appear in gcc 4.8.1, but it does on a very old version (4.4.7), and I think this is the patch (because the defect proposed solution is dated Feb 2012, and this link is dated Mar 2012):

    http://gcc.gnu.org/ml/gcc-patches/2012-03/msg00215.html