C++11: Correct std::array initialization?
Solution 1
This is the bare implementation of std::array
:
template<typename T, std::size_t N>
struct array {
T __array_impl[N];
};
It's an aggregate struct whose only data member is a traditional array, such that the inner {}
is used to initialize the inner array.
Brace elision is allowed in certain cases with aggregate initialization (but usually not recommended) and so only one brace can be used in this case. See here: C++ vector of arrays
Solution 2
According to cppreference. Double braces are required only if =
is omitted.
// construction uses aggregate initialization
std::array<int, 3> a1{ {1,2,3} }; // double-braces required
std::array<int, 3> a2 = {1, 2, 3}; // except after =
std::array<std::string, 2> a3 = { {std::string("a"), "b"} };
Solution 3
C++17 std::array
class template argument deduction (CTAD)
This new C++17 feature is used by the standard library and now allows us to omit the template types as well so that the following works:
main.cpp
#include <array>
int main() {
std::array a{1, 2, 3};
}
instead of std::array<int, 3> a{1, 2, 3};
Tested with:
g++ -ggdb3 -O0 -std=c++17 -Wall -Wextra -pedantic -o main.out main.cpp
If we set -std=c++14
instead for example, it fails to compile with:
error: missing template arguments before ‘a’
See also: Deduce std::array size?
Tested on Ubuntu 18.04, GCC 7.5.0.
Solution 4
Double-braces required in C++11 prior to the CWG 1270 (not needed in C++11 after the revision and in C++14 and beyond):
// construction uses aggregate initialization
std::array<int, 3> a1{ {1, 2, 3} }; // double-braces required in C++11 prior to the CWG 1270 revision
// (not needed in C++11 after the revision and in C++14 and beyond)
std::array<int, 3> a2 = {1, 2, 3}; // never required after =
Related videos on Youtube
Byzantian
Updated on July 05, 2022Comments
-
Byzantian almost 2 years
If I initialize a std::array as follows, the compiler gives me a warning about missing braces
std::array<int, 4> a = {1, 2, 3, 4};
This fixes the problem:
std::array<int, 4> a = {{1, 2, 3, 4}};
This is the warning message:
missing braces around initializer for 'std::array<int, 4u>::value_type [4] {aka int [4]}' [-Wmissing-braces]
Is this just a bug in my version of gcc, or is it done intentionally? If so, why?
-
chris over 11 years
std::array
is an aggregate. I think they might be making it work with one set in the future, however. -
Byzantian over 11 years@chris What exactly, do you mean by that?
-
chris over 11 yearsWell, you know how you can have
struct S {int i; int j;};
and initialize it usingS s = {5, 6};
? That's aggregate initialization.std::array
contains a built-in array, which can be initialized via an initializer list, which is what the inner set is. The outer set is for aggregate initialization. -
Byzantian over 11 years@chris So in my case "{1, 2, 3, 4}" is just a std::initializer_list object which itself has to be placed within the actual initialization braces?
-
chris over 11 yearsWell, I'm not overly sure of how built-in array initializer lists are handled after the introduction of that type, but that's the gist of it, yes. One's for the class, and the other is for the array inside the class.
-
ildjarn over 11 years@cyberpunk_ : A C-array is an aggregate by definition. Given that
std::array<>
is an aggreate also, the first brace initializes thestd::arrat<>
, and the second initializes the inner C-array. -
Jonathan Wakely over 11 years
-
underscore_d almost 7 yearsPossible duplicate of When can outer braces be omitted in an initializer list?
-
-
Cubbi over 11 yearsAll versions of the standard allow brace elision.
-
chris over 11 yearsHuh, stupid GCC warnings >.> I wasn't aware that it was the case already.
-
Cubbi over 11 years@cyberpunk_ only if your compiler implemented DR #1270 which lifts that restriction.
-
Byzantian over 11 years@Chubbi But why does it give me a warning for "std::array<int, 4> a = {1, 2, 3, 4}" then?
-
Cubbi over 11 years@cyberpunk_ It's just a bogus warning.
-
Byzantian over 11 years@Cubbi But annoying nonetheless. There has to be a way to get rid of it.
-
Cubbi over 11 years@cyberpunk_ You can trivially satisfy it with the extra braces. It's not the only annoying warning GCC has (ever seen
suggest parentheses around ‘&&’ within ‘||’
?) -
Jonathan Wakely over 11 yearsYou asked for warnings so you got them, but of course there's a way to get rid of it, use
-Wno-missing-braces
. Or wait for GCC 4.8 which doesn't include-Wmissing-braces
in-Wall
because of thisstd::array
issue. -
Pete Becker over 11 yearsThe warning means that the compiler writer thinks you might not be smart enough to use that language feature correctly.
-
Sam almost 8 yearsI had the same problem (2016 by now), but I fixed it with this syntax: 'std::array<int,4> a[] = {1,2,3,4};' So I added square braces instead of nested curly braces. Maybe someone knows why this variant worked for me?
-
Pubby almost 8 years@Sam That has a different meaning. The syntax you posted is creating an array of std::arrays (a 2-dimensional array), rather than a single array (1-dimensional).