Search code examples
c++arraysunique-ptrdefault-constructorcustom-deleter

How to create an array of unique_ptrs with custom deleters?


Here's what I have:

Demo

#include <cstdio>
#include <memory_resource>
#include <memory>
#include <string_view>
#include <array>
#include <utility> /* declval */


struct msg_outbound_t
{
    std::string_view hello_ = "Hello World!";
};

// Default deleter - works

// using msg_handle_t = std::unique_ptr<msg_outbound_t>;

// Custom deleter - doesn't work

using allocator_t = std::pmr::polymorphic_allocator<std::byte>;

auto pmr_deleter(allocator_t allocator) {
    return [allocator](msg_outbound_t* p) mutable { allocator.delete_object(p); };
}

using msg_handle_t = std::unique_ptr<msg_outbound_t, decltype(pmr_deleter(std::declval<allocator_t>()))>;


int main()
{
    std::array<msg_handle_t, 8> myarray;
}

It doesn't work as it seems that unique_ptrs with custom deleters can't be default constructed? Is there a workaround to create an array of them?

Errors:

<source>:31:33: error: use of deleted function 'std::array<std::unique_ptr<msg_outbound_t, pmr_deleter(allocator_t)::<lambda(msg_outbound_t*)> >, 8>::array()'
   31 |     std::array<msg_handle_t, 8> myarray;
      |                                 ^~~~~~~

Solution

  • it seems that unique_ptrs with custom deleters can't be default constructed?

    Yes, but you'll have to supply a class that it can instantiate as a template parameter:

    using allocator_t = std::pmr::polymorphic_allocator<std::byte>;
    
    struct pmr_deleter {
        void operator()(msg_outbound_t * p) {
             allocator.delete_object(p);
        }
        allocator_t allocator;
    };
    
    using msg_handle_t = std::unique_ptr<msg_outbound_t, pmr_deleter>;
    

    Demo