I have a tuple of smart pointers (as a member of a class template) that I need to initialize. I use std::apply to iterate over tuples elsewhere, but how do I initialize them with new objects without knowing their type? Running the code below with a debugger tells me the elements in the tuple are still "empty" afterwards. What am I doing wrong here?
struct A {
int a = 1;
}
struct B {
int b = 2;
}
std::tuple< std::unique_ptr< A >, std::unique_ptr< B > > my_tuple;
std::apply( [] ( auto&... ptr ) { //std::unique_ptr< T >
(..., ptr.reset( { } )); //ptr.reset( new T() )
}, my_tuple );
As noted in the comments, you can apply decltype
to ptr
to get the type of the unique_ptr
, then apply element_type
to it:
std::apply([](auto &... ptr)
{
((ptr = std::make_unique<typename std::remove_reference_t<decltype(ptr)>::element_type>()), ...);
}, my_tuple );
(I've replaced new
with make_unique
, and moved ...
to the end, but those are just style clanges.)
This can be shortened with C++20 template lambdas:
std::apply([]<typename ...P>(std::unique_ptr<P> &...ptrs )
{
((ptrs = std::make_unique<P>()), ...);
}, my_tuple );