6

The following code is returning the compilation error below. I'm stuck understanding how there are too many initializers. This code works using vector<X>. Does anyone know why the error is being reported and how to resolve? Thanks

#include <iostream>
#include <array>
using namespace std;

struct X {
    int x, y;
};

int main(int argc, char *argv[])
{
    array<X,2> a0 = {{0,1}, {2,3}};

    for (auto& p : a0) {
        cout << p.x << endl;
        cout << p.y << endl;
    }

    return 0;
}

Compilation:

g++ -pedantic -Wall test116.cc && ./a.out
test116.cc: In function ‘int main(int, char**)’:
test116.cc:11:34: error: too many initializers for ‘std::array<X, 2>’
     array<X,2> a0 = {{0,1}, {2,3}};
Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
notaorb
  • 1,944
  • 1
  • 8
  • 18
  • 2
    rule of thumb for `std::array`, if it doesn't work then add extra braces until it does – M.M Jun 07 '20 at 21:50
  • Does this answer your question? [How do you initialize (through initializer lists) a multidimensional std::array in C++11?](https://stackoverflow.com/questions/9504103/how-do-you-initialize-through-initializer-lists-a-multidimensional-stdarray) – JaMiT Jun 07 '20 at 22:58
  • My question was ans below – notaorb Jun 07 '20 at 23:28

3 Answers3

10

Try

array<X,2> a0 = {{{0,1}, {2,3}}};

Note the extra set of braces.

It seems a bit odd but it's this way because the only member of array is the actual array:

template <class T, size_t N>
class array {
    T val[N];
    // ...
};

The constructors are all implicitly defined so that array ends up being a trivially constructable type.

Arthur Tacca
  • 8,833
  • 2
  • 31
  • 49
  • Why are the extra braces required? Also note, I'm copying this nearly identical to Stroustrup C++ 4th Ed Page 208, which shows no errata. – notaorb Jun 07 '20 at 21:47
  • @notaorb Just added an edit. This constructor is implicit... If there were a manually-defined `std::initializer_list` constructor then they wouldn't be needed. – Arthur Tacca Jun 07 '20 at 21:48
  • Sidenote: Brace elision works too: `array a0 {0, 1, 2, 3};` (although I personally think that makes it hard to read). – Ted Lyngmo Jun 07 '20 at 21:49
  • Outer: initialiser for the array; middle: initialiser for the one member (the _actual_ array); inner: initialisers for the Xs. This is what happens when basic, fundamental features of the language are hacked in as user-defined types in the library – Asteroids With Wings Jun 07 '20 at 21:52
  • 1
    @notaorb the language standard for braced initialization keeps changing; it might have been correct at the time of publication! – M.M Jun 07 '20 at 22:00
  • 1
    The implicit construction is similar to `struct Z {int x[2];};` and `struct Z zz = {{0, 1}};`. – notaorb Jun 07 '20 at 22:00
  • Tysm bro. u saved my assignment. – Ah_bb Mar 11 '22 at 20:05
3

You may use one of the following initializations because std::array is an aggregate that contains another aggregate as its data member.

array<X,2> a0 = { { { 0, 1 }, { 2, 3 } } };
array<X,2> a0 = { 0, 1, 2, 3 };
array<X,2> a0 = { { 0, 1, 2, 3 } };
array<X,2> a0 = { { 0, 1, { 2, 3 } } };
array<X,2> a0 = { { { 0, 1 }, 2, 3 } };
Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
  • ... and they say C++ is strict :-) Both answers got my vote. Putting names to all the different initialization versions might provide some extra value. – Ted Lyngmo Jun 07 '20 at 22:09
0

I found that my problem is related to the version of g++,9.4.0 is ok and 5.4.0 not.version of g++.By the way, the version of g++ is associated with the system version generally.

Crawl.W
  • 403
  • 5
  • 17