std::array is an aggregate class type which may have a trivial, implicitly defaulted constructor. If T is not default-constructible, the implicit default constructor is defined as deleted, as per [class.ctor]/5.3.
As this applies in your case, you cannot construct an object of std::array<NotDefaultConstructable, 5> by default construction. You can, however, construct it by means of aggregate initialization:
#include <array>
struct NotDefaultConstructable {
NotDefaultConstructable(int){};
};
int main() {
std::array<NotDefaultConstructable, 3> arr{1, 2, 3};
}
In this sense, all elements of a std::array object should arguably be initialized, even if they represent a non-present object (yet to be "filled", if you will).
You could either find a an appropriate static vector container, such as boost::static_vector, or you could e.g. implement a thin wrapper around std::array which stores an array as above as well its runtime size. Another alternative would be to use a std::array of optionals:
#include <array>
#include <iostream>
#include <optional>
struct NotDefaultConstructable {
NotDefaultConstructable(int val) : val_(val) {};
int val_;
};
int main() {
std::array<std::optional<NotDefaultConstructable>, 3> arr{};
arr[1] = NotDefaultConstructable{42};
for(const auto& element : arr) {
if(element.has_value()) {
std::cout << "has value: " << element.value().val_;
} // has value: 42
}
}
where no dynamic memory allocation takes place (cppreference):
If an optional contains a value, the value is guaranteed to be allocated as part of the optional object footprint, i.e. no dynamic memory allocation ever takes place.
aVis an empty vector.aV.reserve(5)does not make it an vector of 5NotDefaultConstructablesNotDefaultConstructable aV[5]won't work either: godbolt.org/z/8MvxToNotDefaultConstructableobjects btw)