5

the following code doesn't compile with gcc 4.7.0 (using std=c++11 -O3)

int n;
std::vector< int[4] > A;
A.resize(n);

the error message is length, but eventually

functional cast to array type ‘_ValueType {aka int[4]}‘

Is this correct? or should this compile? And more importantly, how to avoid this problem? (without defining a new struct to hold the int[4])

EDIT:

how to solve the problem with C++98?

Walter
  • 44,150
  • 20
  • 113
  • 196

3 Answers3

9

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. Arrays are neither.

You can, however, use an array class template, like the one provided by Boost, TR1, and C++0x:

std::vector<std::array<type, size> >

(You'll want to replace std::array with std::tr1::array to use the template included in C++ TR1, or boost::array to use the template from the Boost libraries. Alternatively, you can write your own; it's quite straightforward.)

@source By:James McNellis

So the code would look like:

int n;
std::vector<std::array<int,3>> A;
A.resize(n);
Community
  • 1
  • 1
heretolearn
  • 6,387
  • 4
  • 30
  • 53
  • 1
    That doesn't do what the OP wants at all. All that does is create a vector of ints that has an initial length of 4, not a vector of 4-length int-arrays. – KRyan Aug 29 '12 at 19:18
  • Sorry, i understood it wrong, However i have edited my answer. Hope it helps – heretolearn Aug 29 '12 at 19:26
  • @R.MartinhoFernandes: Infer what? My first comment was referring to an older version of sshekhar's answer, which was incorrect. He's edited the answer so that now it actually answers the question, so I removed the downvote I had given it. – KRyan Aug 29 '12 at 19:37
  • 1
    Note, in C++11 the requirement is no longer copy assignable and copy constructable, but varies based on function being called. In particular, the method he is calling requires default constructable. – Dave S Aug 29 '12 at 19:41
  • 1
    @DaveS if this is true (which seems reasonable, since in C++11 `std::vector` has two versions of `resize()`, one with just one argument of `size_type` and one with a second argument of `value_type const&`), then my code should work because `std::is_default_constructible::value == true` – Walter Aug 30 '12 at 07:57
  • @Walter I believe that's correct and that there's simply a bug in the C++11 library implementation you're using. – bames53 Mar 15 '13 at 23:59
4

without defining a new struct to hold the int[4]

Impossible. You have to either define or find a struct (std::array, std::tr1::array, boost::array). Else, this code will never compile.

Puppy
  • 144,682
  • 38
  • 256
  • 465
  • 1
    why? does it violate an explicit requirement for `std::vector`? – Walter Aug 29 '12 at 19:10
  • @Walter: "why?" Because the Specification for Programming Language C++ says so. – Nicol Bolas Aug 29 '12 at 19:20
  • @NicolBolas which specification in particular? – Walter Aug 30 '12 at 07:51
  • There is only one- The International Standard ("The Standard"), now known as C++11. – Puppy Aug 30 '12 at 07:57
  • 1
    @DeadMG this comment is close to being flaggable as unconstructive/offensive. The standard *consists* of specifications, but isn't one. Please refrain from making useless comments. – Walter Aug 30 '12 at 08:09
  • @Walter: Now you're just quibbling over semantics; in this context, "standard" and "specification" are generally interchanagable. The point is that the C++ language defines this to not work. Why it does so is irrelevant. – Nicol Bolas Aug 30 '12 at 10:00
  • 2
    @Walter: vector elements have to be assignable, i.e. you must instantiate `vector` only with types T that are assignable. `int[4]` isn't. You can't assign one `int[4]` to another. You _can_ assign one `array` to another (which of course repeatedly does memberwise assignment). – MSalters Aug 30 '12 at 14:05
2

See 23.1/3:

The type of objects stored in these components must meet the requirements of CopyConstructible types (20.1.3), and the additional requirements of Assignable types.

Thus in C++03 vector requires the contained items to be copy constructable, which C-style arrays are not. The error message is correct and the code should fail to compile. Just use a vector of vectors, a struct to wrap your array, or vector of std::array in C++11.

Note that I believe the copy-constructable restriction is lifted container-wide in C++11 and I'm not sure if/how you could store C-style arrays within one or if it's prohibited more explicitly.

Mark B
  • 95,107
  • 10
  • 109
  • 188
  • I don't think so. in C++11, `std::vector::resize(size_type)` does not take a second argument (there is a version taking a second argument) and should use the default constructor, not the copy constructor. – Walter Aug 30 '12 at 07:53
  • @Walter the OP says C++98 (and presumably within C++03 as well) not C++11. – Mark B Aug 30 '12 at 13:59