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 delete
d 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?

- 14,902
- 5
- 47
- 92
-
3I wonder what would be `v[0]` after `std::vector
v(1);` – Vlad Aug 01 '12 at 16:07 -
I know it's weird, that's why I'm asking. – Cubic Aug 01 '12 at 16:09
-
7Only *certain operations* requires default constructibility. @Vlad gave an example. If you stay away from those, all is well. – R. Martinho Fernandes Aug 01 '12 at 16:10
-
If that's the only problem with this, then I don't actually have any problems with this - I don't particularly need that constructor, and I'd have to jump through hoops to provide a reasonable default constructor. Which would still not be reasonable, because the instance wouldn't be capable of doing anything other than existing, everything else would throw an exception. – Cubic Aug 01 '12 at 16:12
-
1Although it is not always better, consider storing pointers (preferably smart) if your object has problems with construction, destruction or copying. – Daniel Aug 01 '12 at 16:19
-
@Vlad: that would not compile. `std::vector` per se does not require a default constructor, but some of the operations do, in particular the constructor you are using takes a second argument by const-reference, although it is defaulted to `T()`. – David Rodríguez - dribeas Aug 01 '12 at 18:37
-
@David: I see this now, but at the beginning I was interpreting the OP's question as "std::vector works completely ok with non-default-constructible template parameter". Thank you anyway. – Vlad Aug 01 '12 at 22:33
4 Answers
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.

- 206,506
- 52
- 449
- 577
-
7Also calling emplace_back() and emplace(const_iterator position) [using those specific signatures]. – Nevin Aug 01 '12 at 19:09
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

- 223,364
- 34
- 402
- 480
-
2I can meet all of those, just `DefaultConstructible` is a problem for me. – Cubic Aug 01 '12 at 16:22
-
1In a quick glance over the standard I only found the constructor `explicic vector(size_type n);` that explicitly requires elements to be DefaultConstructible. – jrok Aug 01 '12 at 16:29
-
-
4
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.

- 312,472
- 42
- 525
- 765
-
Hm. What about `std::vector
v(1);`? This was legal in C++03 as well and has to default-construct `v[0]`. – Vlad Aug 01 '12 at 16:57 -
1@Vlad: The "classis" vector's constructor takes more than one parameter. You simply don't see them because the have default arguments. When you do `std::vector
v(1)` it actually stands for `std::vector – AnT stands with Russia Aug 01 '12 at 16:59v(1, T(), A())` (the last argument is allocator). I.e. it is still *you*, not vector, who's default-constructing that `T()` and sending its to the constructor for copying. -
Well, it's perhaps call-site, not the developer using the code, as he actually didn't default-construct anything. Anyway, it's nitpicking from my side. +1 for nice observation. – Vlad Aug 01 '12 at 17:03
-
1@Vlad: By "the caller" I meant "the calling code", not the developer who wrote it. – AnT stands with Russia Aug 01 '12 at 17:09
-
But what would `some_type()` mean, other than a default constructed instance? – juanchopanza Aug 01 '12 at 17:19
-
2@juanchopanza: It *is* a default constructed instance, as I said above. The point is that in pre-C++11 library the default constructed instance is *always created outside* and supplied from *outside*, as an argument. Default-construction is *never* performed by the vector internally. Meanwhile, in C++11 default-construction can be performed internally. – AnT stands with Russia Aug 01 '12 at 17:25
-
@AndreyT but without a default constructible element type, I cannot see how a call to vector
(size_type) could actually work. – juanchopanza Aug 01 '12 at 17:33 -
1@juanchopanza: What version of library specification are you talking about? The first part of my answer applies to C++98/C++03. There's no such thing as `vector
(size_type)` in C++98/C++03. C++98/C++03 only has `vector – AnT stands with Russia Aug 01 '12 at 17:44(size_type, const T& = T(), const A& = A())`. And that's exactly what is used when you do `vector v(42)`. -
@AndreyT I was talking about C++03. OK, so my question was how could `vector
v(42)` work without a default constructible `T`? Sorry if I was unclear before. – juanchopanza Aug 01 '12 at 18:06 -
1@juanchopanza: `vector
v(42)` cannot work without default-constructible `T`. As I said above, in C++03 `vector – AnT stands with Russia Aug 01 '12 at 18:15v(42)` is interpreted by the compiler as `vector v(42, T(), A())`, which simply won't compile for non-default-constructible `T`. I'm not arguing with that. The only point I'm making about C++03 is that the default construction in this case is performed in the context of the calling code (arguments are always prepared by the calling code), not internally by the vector. In C++11 it would be done internally by the vector. -
1@AndreyT, an excellent answer, just one quibble: C++03 17.4.4.4 [lib.member.functions] means it is conforming for an implementation to define `vector::resize` as a pair of overloaded functions, one of which would default-construct an element internally (not at the call site), similarly for the `vector(size_type, T)` constructor -- so that was always allowed in C++03, so you cannot rely on the semantics you claim. – Jonathan Wakely Aug 01 '12 at 18:26
-
@Jonathan Wakely: Yes, thanks for this note. Good point. It is present in C++98 as well. In other words, C++11 implementation conforms to by C++98 requirements. – AnT stands with Russia Aug 01 '12 at 20:41
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.

- 35,022
- 6
- 77
- 199
-
4In C++03, the standard actually *requires* that the elements be `CopyConstructible` and `Assignable`. So the compiler is allowed to detect a missing copy constructor, for example. This changes in C++11. – juanchopanza Aug 01 '12 at 16:17
-
@juanchopanza: I wonder if the `vector` implementations of the major C++03-compatible compilers check these constraints at e.g. simple declaration: `std::vector
* pv;`. (Have no old compiler at hand.) – Vlad Aug 01 '12 at 16:25 -
I cannot get it to fail using gcc 4.7 and a vector of boost:noncopyable-derived classes. – juanchopanza Aug 01 '12 at 16:48
-
They don't check the requirements, but using a type not fulfilling all requirements *will* break library code, and in different places for different compilers. – Bo Persson Aug 01 '12 at 16:50
-
3It is not forbidden for a compiler to accept code that goes outside what is the minimum requirement. – Bo Persson Aug 01 '12 at 16:52
-
1@juanchopanza: if the standard _requires_ `CopyConstructible` etc., I would expect that the compiler _must_ detect, not _may_. But well, the compiler writers know it better anyway. – Vlad Aug 01 '12 at 16:53
-
@BoPersson: but if the code happens to compile but fails to satisfy the requirements, does this technically mean UB? – Vlad Aug 01 '12 at 16:55
-
1@Vlad - It probably just means *extremely non-portable*. Suppose you just create a `vector
v;` and call `v.size()` on the empty vector. Is it bad if that compiles? – Bo Persson Aug 01 '12 at 17:01 -
@BoPersson: being an adherent of tyrannical discipline in code, I tend to say "yes". – Vlad Aug 01 '12 at 17:02
-
@Vlad I was expecting the same, so I find it strange that the requirement isn't strictly adhered to. Unless I am misreading these requirements, or have missed some caveats somewhere else in the standard. – juanchopanza Aug 01 '12 at 17:21
-
@Vlad, _"I wonder if the vector implementations of the major C++03-compatible compilers check these constraints"_ GCC with `-D_GLIBCXX_CONCEPT_CHECKS` will check some constraints, but it's not done by default. Another (not 100% reliable) way to check them is to explicitly instantiate `vector
` and see if it works. – Jonathan Wakely Aug 01 '12 at 18:29