21

See this example: https://godbolt.org/z/5PqYWP

How come this array of pairs can't be initialized in the same way as a vector of pairs?

#include <vector>
#include <array>

int main()
{
    std::vector<std::pair<int,int>>    v{{1,2},{3,4},{5,6}}; // succeeds 
    std::array <std::pair<int,int>, 3> a{{1,2},{3,4},{5,6}}; // fails to compile
}
3
  • 2
    A very similar question was asked today, but with a struct instead of a std::pair. But the answer there is much the same as any here would be, IMHO. (Or maybe not - that one is about an assignment rather than a constructor?) Commented Dec 8, 2020 at 11:28
  • 2
    @AdrianMole but with a struct instead of a std::pair I would expect that the std::pair is actually a (template) struct. ;-) Commented Dec 8, 2020 at 11:31
  • 1
    @Scheff I can't disagree (even if I wanted to, which I don't). Commented Dec 8, 2020 at 11:32

2 Answers 2

24

You need to add an outer pair of braces to initialize the std::array<...> object itself:

std::array <std::pair<int,int>, 3> a{{{1,2},{3,4},{5,6}}};

The outermost pair is for the array object, the second pair is for the aggregate array inside the object. Then the list of elements in the array.

Sign up to request clarification or add additional context in comments.

5 Comments

So why is vector different from array?
std::array is an aggregate, so you need {} to construct the std::array class, and a {} to construct it's member array. std::vector has a constructor that takes a std::initializer_list, so the {} to construct the vector automatically calls that.
@MooingDuck Ah, so it's actually two different mechanisms? An explicit constructor with vector, and a plain old aggregate initialization with array?
@MooingDuck Also: Could I aggregate-initialize a std::vector (which surely also is an aggregate)?
@Peter-ReinstateMonica: No. an "Aggregate" is basically "a class whose members are all public and has no explicit constructors", which lets you directly construct the array member of the std::array. Instead, std::vector has private members that you can't access yourself, and custom constructors, so it's not an aggregate.
14

Specializations of the class template std::array represent aggregates that enclose another aggregate.

The reason of the error is that the first braced initializer in this declaration

std::array <std::pair<int,int>, 3> a{{1,2},{3,4},{5,6}};
                                     ^^^^^

is considered as an initializer of the inner aggregate. In this case the following braced initializers are considered as redundant initializers.

So you can write either

std::array <std::pair<int, int>, 3> a{ { {1,2},{3,4},{5,6} } };
                                       ^                   ^
                                       |the inner aggregate|

or like

std::array <std::pair<int, int>, 3> a{ std::make_pair( 1, 2 ), std::make_pair( 3, 4 ), std::make_pair( 5, 6 ) };

4 Comments

It's worth mentioning that std::array doesn't have a initializer_list constructor, which vector does.
@iwans std::array is an aggregate. It does not have user declared constructors.:)
@VladfromMoscow That's too bad, isn't it?
@Peter-ReinstateMonica I do not think so. This class (aggregate) simulates an array that in turn is an aggregate.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.