Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ vector of arrays

Why does this work:

std::pair<int, int> p = {1,2}; std::vector<std::pair<int, int>> vp = { {1,2}, {3,4} }; 

But this doesn't?

std::array<int, 2> a = {1,2}; // still ok std::vector<std::array<int, 2>> va = { {1,2}, {3,4} }; 

Using g++ 4.5.1 with -std=c++0x, the second line fails with:

error: could not convert ‘{{1, 2}, {3, 4}}’ to ‘std::vector<std::array<int, 2u> >’

Thanks

like image 874
andreabedini Avatar asked May 18 '11 07:05

andreabedini


People also ask

Can you make a vector of arrays?

You cannot store arrays in a vector or any other container. The type of the elements to be stored in a container (called the container's value type) must be both copy constructible and assignable.

Can you have a vector of arrays C++?

Vectors in C++ are sequence containers representing arrays that can change in size. They use contiguous storage locations for their elements, which means that their elements can also be accessed using offsets on regular pointers to its elements, and just as efficiently as in arrays.

What are the vectors in array?

We can think of a vector as a list that has one dimension. It is a row of data. An array is a list that is arranged in multiple dimensions. A two-dimensional array is a vector of vectors that are all of the same length.

Is vector same as array in C?

Vector is template class and is C++ only construct whereas arrays are built-in language construct and present in both C and C++. Vector are implemented as dynamic arrays with list interface whereas arrays can be implemented as statically or dynamically with primitive data type interface.


2 Answers

Unfortunately, std::array does not have an initializer list constructor. Indeed, it has no user-defined constructor whatsoever -- this "feature" is a leftover from C++03 where omitting all user-defined constructors was the only way to enable the C-style brace initialization. It is IMHO a defect in the current standard.

So why doesn't built-in brace initialization work in this case? Let's see what std::array looks like under the hood:

template <typename T, int i> struct array {     T data[i];     // ... } 

Ok, so doesn't that mean we'd have to use double braces in the initializer (one pair for array, another pair for the data member?

std::array<int, 2> a = { {1, 2} }; 

C (and consequently C++) has a special rule about brace elision, permitting the omission of the inner braces unless there is an ambiguity. array exploits this feature, allowing us to write

std::array<int, 2> a = { 1, 2 }; 

So why doesn't the example in the original post work? Because brace elision is only permitted in the context of a C-style aggregate initialization, not if there's anything more complicated involved, such as an user-defined initializer list constructor.

The following should work, though, as ugly as it is:

std::vector<std::array<int, 2>> vp = { {{1,2}}, {{3,4}} }; 

The fact that it does not, at least on gcc 4.5 and gcc 4.6, seems to me to indicate a compiler bug. I'm not completely sure about it, though.

This question is somewhat relevant: How do I initialize a member array with an initializer_list?

like image 182
JohannesD Avatar answered Sep 25 '22 14:09

JohannesD


This works:

std::vector<std::array<int, 2>> va = {   std::array<int, 2>{1,2},   std::array<int, 2>{3,4} }; 

Digging deeper, it seems that std::pair has a constructor that takes an initialiser list, but std::array doesn't:

std::pair<int, int> p ({1,2}) ;  // OK std::array<int, 2> a ({1,2}) ;   // Invalid 

But now I'm out of my depth.

like image 43
TonyK Avatar answered Sep 23 '22 14:09

TonyK