Reputation: 1750
It's an exercise from C++ Primer 5th Edition:
Exercise 16.26: Assuming NoDefault is a class that does not have a default constructor, can we explicitly instantiate
vector<NoDefault>
? If not, why not? P.677
I know it doesn't compile if class NoDefault
has no default constructor, but can not explain the reason. Can anyone tell me how is the default constructor used while explicitly instantiating template class std::vector<NoDefault>
?
Upvotes: 6
Views: 1805
Reputation: 76280
While explicitly instantiating
std::vector<someType>
, what is the someType default constructor used for?
It's used to construct the elements of the array when resizing the std::vector
. For example:
std::vector<T> vector(10);
will default construct 10 elements of type T
.
Upvotes: 3
Reputation: 279315
C++11 introduces a new constructor, vector(size_type n)
, and "obviously" that constructor can't be instantiated unless the value_type
is default-constructible. It was vector(size_type n, const T & = T(), const Allocator& alloc = Allocator())
in C++03, but they changed it to two separate constructors. A similar change was made to resize()
.
In GCC and as far as I know also per the standard: the vector
template can be at least implicitly instantiated without the elements being default constructible. Implicit template class instantiation only instantiates the member functions you use.
In C++03 only the default arguments use default construction. You can explicitly instantiate the template, but you won't be able to call those functions without providing a value for that parameter.
So I'm pretty sure that change is what prevents vector<NoDefault>
being explicitly instantiated in C++11 (and I suppose the allocator type needs to be default-constructible too). But I might have missed something. It seems a little odd to make that change given that it introduces this backward incompatibility. There's probably a proposal somewhere that justifies it if you want a deeper reason why this no longer works as opposed to just why this doesn't work :-)
Upvotes: 7
Reputation: 5039
As already said, the default constructor is required to create vector of objects. However, if one were to create a classic dynamic array (contiguous area of memory), it would be possible to address the lack of a default constructor using the placement new syntax:
#include <iostream>
struct Foo {
explicit Foo(int a): a(a) {}
int a;
};
int main() {
void* mem = operator new[](10*sizeof(Foo));
Foo* ptr = static_cast<Foo*>(mem);
for (int i = 0; i < 10; ++i ) {
new(&ptr[i])Foo(i);
std::cout << ptr[i].a;
}
return 0;
}
Upvotes: 0