c++unique-ptrstdtuplestdapply

Initializing smart pointers in a tuple without knowing the type


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 );

Solution

  • 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 );