Cubic
Cubic

Reputation: 15683

std::vector works with classes that are not default constructible?

I've read in several places that std::vector requires it's template argument to be default constructible. Today I just tried it with one of my classes that has a deleted default constructor, and to my surprise it seems to be working just fine (with std::vector's default constructor). Is this portable behavior, or is this an implementation detail of gcc's STL and should I assume vector to require it's template argument to be default constructible?

Upvotes: 12

Views: 5010

Answers (4)

Howard Hinnant
Howard Hinnant

Reputation: 219185

There are two vector<T> members that require a default constructible T in C++11:

explicit vector(size_type n);
void resize(size_type sz);

Nothing else does. So if you use these signatures, you need to have a default constructible type, else you do not.

Upvotes: 22

AnT stands with Russia
AnT stands with Russia

Reputation: 320631

std::vector does not unconditionally require its elements type to be default-constructible.

The original specification of std::vector (C++98, C++03) never even attempts to default-construct its elements internally. All new elements are always copy-constructed from an object supplied "from outside" (by the calling code) as an argument. This means that every time you need default-constructed elements in your vector, it is your side of the code (the caller) that has to default-construct it and supply it to std::vector as the "original" element to be copied.

For example, when you do something like this in C++98

std::vector<some_type> v(42);
v.resize(64);

it actually expands into

std::vector<some_type> v(42, some_type(), allocator_type());
v.resize(64, some_type());

through the default argument mechanism. In other words, the default-constructed "original" element is supplied to vector's constructor by the calling code, not created internally by the vector.

C++11 changed that and now std::vector has methods that perform default construction of its elements internally. This still does not unconditionally require vector elements to be default-constructible. It just means that you need default-constructible elements to use those specific std::vector's methods.

Upvotes: 8

juanchopanza
juanchopanza

Reputation: 227468

The requirement in C++03 is that types being stored in a container be CopyConstructible and Assignable (see §23.1 Container Requirements). However, in C++11 these requirements are relaxed, and tend to apply to the operations performed on the container. So a simple default construction has no requirements (see teble 96, §23.1 in C++11 standard).

As soon as you try to copy a vector, or insert elements into it, you will meet the CopyInsertable, CopyAssignable, EmplaceConstructible, MoveInsertable, MoveAssignable etc. requirements

Upvotes: 15

Vlad
Vlad

Reputation: 35594

Well, templates are in some meaning weakly typed. That is, the missing default constructor won't be detected until your code calls the method where it's used, perhaps internally -- this will give a compile-time error.

However, unless you are not touching the methods which use the default constructor internally, you are "safe". However, I don't know which is the "safe" subset, and I suspect that it's not defined by the standard. Example: vector copying might use resize, which in turn might use default constructor.

Upvotes: 4

Related Questions