0

recently I've started to study C++'s standard library containers from the Deitel&Deitel book. Conceptually, it is quite clear to me, but I have a problem when trying to replicate a piece of code that includes a 2-D array initialization.

The initialization in the book is (pretty much) this one:

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

int main(){

    array<array<int, 3>, 10> grades{{87, 96, 70},
        {68, 87, 90},
        {94, 100, 90},
        {100, 81, 82},
        {83, 65, 85},
        {78, 87, 65},
        {85, 75, 83},
        {91, 94, 100},
        {76, 72, 84},
        {87, 93, 73}};
  }

This shouldn't be problematic, but VisualStudioCode returns an error saying "too many initialization values". If instead, I simply initialize it in this way:

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

int main(){

    array<array<int, 3>, 10> grades{87, 96, 70,
        68, 87, 90,
        94, 100, 90,
        100, 81, 82,
        83, 65, 85,
        78, 87, 65,
        85, 75, 83,
        91, 94, 100,
        76, 72, 84,
        87, 93, 73};
    }

it works, which is what I do expect since the book in a previous example initialized a 2-D array by linearizing all its elements. What I do not understand is why in the other case VSC returns that error, since it should work just fine.

FraTsuna
  • 1
  • 2

2 Answers2

0

It is down to a typo. Thhis works, count the braces. Live demo here : https://godbolt.org/z/xqTWxEEov

#include <iostream>
#include <array>
// using namespace std; // <== unlearn to do this.

int main()
{
    std::array<std::array<int, 3>, 10> grades{{
        {87, 96, 70},
        {68, 87, 90},
        {94, 100, 90},
        {100, 81, 82},
        {83, 65, 85},
        {78, 87, 65},
        {85, 75, 83},
        {91, 94, 100},
        {76, 72, 84},
        {87, 93, 73}}};

        for(const auto entry : grades)
        {
           auto [v1,v2,v3] = entry;
           std::cout << v1 << ", " << v2 << ", " << v3 << "\n";
        }
  
        return 0;
  }
Pepijn Kramer
  • 9,356
  • 2
  • 8
  • 19
0

The class template std::array is an aggregate that under the hood represents a structure with a data member of an array type..

The compiler considers in this initialization

array<array<int, 3>, 10> grades{{87, 96, 70},
    {68, 87, 90},
    {94, 100, 90},
    {100, 81, 82},
    {83, 65, 85},
    {78, 87, 65},
    {85, 75, 83},
    {91, 94, 100},
    {76, 72, 84},
    {87, 93, 73}};

the first list

{87, 96, 70} 

as a whole initializer for the array grades.

To consider the lists as initializers for the inner elements of the type std::array<int, 3> you need to add one more pair of braces.as shown in the demonstration program below.

#include <iostream>
#include <array>

int main()
{
    std::array<std::array<int, 3>, 10> grades
    {
        {
            {87, 96, 70},
            {68, 87, 90},
            {94, 100, 90},
            {100, 81, 82},
            {83, 65, 85},
            {78, 87, 65},
            {85, 75, 83},
            {91, 94, 100},
            {76, 72, 84},
            {87, 93, 73}
        }
    };

    for ( const auto &row : grades )
    {
        for ( const auto &item : row )
        {
            std::cout << item << ' ';
        }
        std::cout << '\n';
    }
}

The program output is

87 96 70 
68 87 90 
94 100 90 
100 81 82 
83 65 85 
78 87 65 
85 75 83 
91 94 100 
76 72 84 
87 93 73 

As the inner element has the type std::array<int, 3> then by analogy you could add one more pair of braces around each initializer list like

std::array<std::array<int, 3>, 10> grades
{
    {
        { {87, 96, 70} },
        //...
Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335