Narek Narek - 3 months ago 8
C++ Question

Why I can't desalinize std::array like this?

Why I can't desalinize std::array like this?

#include <array>

struct Point
{
float x;
float y;
};

int main()
{
std::array<Point, 3> m_points {
{ 1.0f, 1.0f },
{ 2.0f, 2.0f },
{ 3.0f, 3.0f }
};
}


Doing this I get error:


error: too many initializers for
std::array<Point, 3ul>



but it works like this:

std::array<Point, 3> m_points {
Point{ 1.0f, 1.0f },
Point{ 2.0f, 2.0f },
Point{ 3.0f, 3.0f }
};


In contrast
std::map
can be initialized with both ways written below:

std::map<int, int> m1 {std::pair<int, int>{1,2}, std::pair<int, int>{3,4}};
std::map<int, int> m2 {{1,2}, {3,4}};

Answer

In this declaration and initialization

   std::array<Point, 3> m_points { 
      { 1.0f, 1.0f }, 
      { 2.0f, 2.0f }, 
      { 3.0f, 3.0f }
   };

the compiler considers the first initializer in braces like the initializer of the whole array (of the internal aggregate). std::array is an aggregate that contains another aggregate.

Write instead

   std::array<Point, 3> m_points {
      { 
      { 1.0f, 1.0f }, 
      { 2.0f, 2.0f }, 
      { 3.0f, 3.0f }
      }
   };

In the second case

std::array<Point, 3> m_points { 
   Point{ 1.0f, 1.0f }, 
   Point{ 2.0f, 2.0f }, 
   Point{ 3.0f, 3.0f } 
};

each initializer is considered sequentially as an initializer of a next element of the internal aggregate.

Consider this simple demonstrative program.

#include <iostream>

struct array
{
    int a[10];
};

int main()
{
    array a = { { 0, 0 }, { 1, 1 } };

    return 0;
}

The compiler issues an error like

prog.cpp:14:33: error: too many initializers for 'array'
  array a = { { 0, 0 }, { 1, 1 } };
                                 ^

That is it decided that { 0, 0 } is an initializer of the internal array (internal aggregate). Thus the next initializer in braces does not have a corresponding data member in the outer aggregate (structure).