Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

std::array aggregate initialization requires a confusing amount of curly braces

Tags:

c++

c++11

I have the following code:

   enum class MessageDeliveryMethod
   {
      POST_MASTER,
      BUBBLE,

      NUM_ENUMERATORS
   };

   namespace
   {
      using MapType = std::array<
         std::pair<char const*, MessageDeliveryMethod>,
         static_cast<std::size_t>(MessageDeliveryMethod::NUM_ENUMERATORS)
      >;

      MapType g_mapping = {{
         {"POST_MASTER", MessageDeliveryMethod::POST_MASTER},
         {"BUBBLE", MessageDeliveryMethod::BUBBLE},
      }};
   }

This compiles but I don't know why. The g_mapping variable requires an extra level of seemingly redundant curly braces. In other words, I expect the initialization to look like:

MapType g_mapping = {
   {"POST_MASTER", MessageDeliveryMethod::POST_MASTER},
   {"BUBBLE", MessageDeliveryMethod::BUBBLE},
};

(One level of outer braces removed).

My understanding is that prior to C++14, when doing direct initialization the extra level of braces is required. However, copy initialization was not supposed to require this based on this page (look at the example there).

Can anyone explain this?

UPDATE:

This SO question which is presumed to be duplicated by my question does indeed answer some specific and helpful questions (related to my own) however out of context mine was confusing due to the usage of pair (which I thought was causing the issue initially). I never would have found that SO question in the first place, so if anything I think perhaps the way I've worded my question may help people arrive to the solution from different angles.

like image 342
void.pointer Avatar asked Mar 19 '15 16:03

void.pointer


2 Answers

std::array is defined as a structure that contains an array.

Thus the first pair of braces are used to initialize data members of the structure that is the array. The second pair of braces is used to initialize the array within the structure. And the third pairs of braces are used to initialize each object of type std::pair.

To be more precise then according to the C++ Standard (23.3.2.1 Class template array overview)

2 An array is an aggregate (8.5.1) that can be initialized with the syntax

array<T, N> a = { initializer-list }; 

where initializer-list is a comma-separated list of up to N elements whose types are convertible to T.

like image 127
Vlad from Moscow Avatar answered Oct 17 '22 08:10

Vlad from Moscow


std::array is defined to be a nested aggregate - a class containing an array as its only member. Prior to C++14, aggregate initialisation needed two levels of braces: one to surround the class member list (in which there was only one member, the array), and one to surround the array element list. Then you need a third level if, as here, you want to list-initialise each array element.

C++14 allows you to "flatten" the lists when initialising nested aggregates, as described in the page you link to.

like image 20
Mike Seymour Avatar answered Oct 17 '22 08:10

Mike Seymour