How to create a vector of unique pointers pointing at default constructed objects
Is there a way to create a vector containing N number of std::unique_ptr<T>
s? GCC v11.2 shows huge and cryptic error messages so I'm not able to detect the issue.
Here is an MRE of what I was trying to do:
#include <iostream>
#include <vector>
#include <memory>
// a dummy struct
struct Foo
{
int m_value;
};
int main( )
{
constexpr auto rowCount { 10uz };
constexpr auto colCount { 20uz };
// a 1D vector of pointers, does not compile
std::vector< std::unique_ptr<Foo> > vec_1D( colCount, std::make_unique<Foo>( ) );
for ( const auto& ptr : vec_1D )
{
std::cout << "Address: " << ptr << " --- value: " << ptr->m_value << '\n';
}
// a 2D vector of pointers, does not compile
std::vector< std::vector< std::unique_ptr<Foo> > >
matrix( rowCount, std::vector< std::unique_ptr<Foo> >( colCount, std::make_unique<Foo>( ) ) );
}
I think I'm missing something important about std::unique_ptr
here. Is this error because of the fact that unique_ptr
is not copy-constructible?
If the above method is not possible, then what could be the alternative?
The line:
std::vector< std::unique_ptr<Foo> > vec_1D( colCount, std::make_unique<Foo>( ) );
makes use of the following vector constructor:
vector( size_type count, const T& value, const Allocator& alloc = Allocator());
Which receives a given value and copies it to every element of the vector. From cppreference:
- Constructs the container with count copies of elements with value value.
So you are calling std::make_unique<Foo>()
, getting a std::unique_ptr<Foo>&&
back from that call, and passing it to the std::vector
's constructor so that it copies it across. The problem is that that unique pointer is not copyable.
You could though:
- create a vector with a given size, and
- for every element in the vector,
- create a unique pointer (one at a time), and
- move assign that unique pointer to the vector's element.
The example below uses std::generate
to fill the vector. Notice that the generator function is returning a std::unique_ptr<Foo>&&
that is move assignable to each vector's element.
[Demo]
#include <algorithm> // generate
#include <iostream> // cout
#include <memory>
#include <vector>
// a dummy struct
struct Foo
{
Foo() : m_value{value++} {}
static inline int value{};
int m_value{};
};
int main( )
{
const size_t count{ 20 };
std::vector<std::unique_ptr<Foo>> v(count);
std::generate(v.begin(), v.end(), []() { return std::make_unique<Foo>(); });
for (auto&& up : v) { std::cout << up->m_value << " "; }
}
// Outputs
//
// 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19