mosg
mosg

Reputation: 12391

HowTo init boost::array with custom structure?

I'm looking for a nice solution is how to initialize a static boost::array with a custom user structure and data. My example, what I'm expecting from boost::array, below:

 struct Foo
 {
      std::string a;
      std::string b;
 };
 static boost::array< Foo, 2 > foo =
 {
      { "111", "222" },
      { "333", "444" },
 };

But this code didn't work,

error C2078: too many initializers

What I'm missing?

Thnks!

Upvotes: 1

Views: 793

Answers (2)

Komi Golov
Komi Golov

Reputation: 3471

This is caused by the way brace elision works. From N3485, 8.5.1.11:

Braces can be elided in an initializer-list as follows. If the initializer-list begins with a left brace, then the succeeding comma-separated list of initializer-clauses initializes the members of a subaggregate; it is erroneous for there to be more initializer-clauses than members. If, however, the initializer-list for a subaggregate does not begin with a left brace, then only enough initializer-clauses from the list are taken to initialize the members of the subaggregate; any remaining initializer-clauses are left to initialize the next member of the aggregate of which the current subaggregate is a member.

In other words, if the next thing is an initializer-list, we can assume no brace elision has occurred. The braces are inserted at the innermost level, and so while we would like the following

{{"a", "b"}, {"c", "d"}}  -> {{{"a", "b"}, {"c", "d"}}}

we instead get

{{"a", "b"}, {"c", "d"}} -> {{{"a", "b"}}, {"c", "d"}}

Now as to why we can elide even more braces and write {"a", "b", "c", "d"}: once we hit the "a", we know that brace elision has happened, as we expect the array member to be initialised with an initializer-list. We thus start consuming as many initializer-clauses as necessary to initialize the member array. Again, we hit the "a" instead of an initializer-list, and so we start consuming as many initializer-clauses as necessary to initialize the first Foo. We repeat this for the second Foo, consume all clauses, and end up with

{"a", "b", "c", "d"} -> {{{"a", "b"}, {"c", "d"}}}

as desired.

Upvotes: 4

Marshall Clow
Marshall Clow

Reputation: 16700

Adding an extra set of braces works for me.

 static boost::array< Foo, 2 > foo =
 {{
    { "111", "222" },
    { "333", "444" },
 }};

More as I figure out why. I think the key here is "brace elision" (thanks to jesyspa for pointing me there)

This also works:

 static boost::array< Foo, 2 > foo =
 {
    "111", "222",
    "333", "444",
 };

Upvotes: 2

Related Questions