Question

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)

Was it helpful?

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

OTHER TIPS

It is an annoying "safety" warning that was introduced in one of the earlier versions of GCC for both C and C++ aggregate initializers. If I remember correctly, it predates C++11 and is not really related to C++11 (again, it affects C as much as it affects C++). Basically, it requires an additional level of nested {} when beginning an initializer for each nested aggregate. The language does not require this, which is why it is just a warning.

The warning in question could be useful in many cases, but the implementation was poorly thought through. One completely preposterous consequence of that warning is that it "kills" the = { 0 } initializer idiom in C language. (In C anything can be initialized with = { 0 }, but because of this annoying warning one is forced to selectively use things like = {{0}}, = {{{0}}} and such).

In C++ std::array class is an aggregate, for which = { ... } initializers are handled by the good-old built-in aggregate initialization, not by a dedicated constructor. (In C++11 the rules of aggregate initialization were rewritten in terms of initializer lists, but the general C-style behavior was intentionally preserved through the possibility of brace elision.) For this reason std::array initialization is also affected by that warning. std::array is an aggregate containing the actual array, which is also an aggregate. For this reason, in order to get to the array elements in the initializer GCC encourages you to open two levels of {}.

So, with std::array you just found another example of when that warning does more harm than good.

No, there's really no way in which a reasonable compiler can screw this up, for a class this simple.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top