There is an array holding unique pointers:
std::array<std::unique_ptr<T, deleter<allocator<T>>>> storage;
where
template<typename ALLOC>
class deleter {
void operator()( void ) { ... }
};
does the deletion as required by unique_ptr. Effectively, it calls the destructor and then deallocates the memory occupied. So far so good.
But there is another deleter:
template<typename T>
class empty_deleter {
void operator()( void ) {}
};
which performs no operation at all - no destruction, no deallocation.
The reason why it exists is to have, in theory, the option to store object owned by such unique_ptr<T, empty_deleter<T>>
within the storage array...
The question is - how to achieve that? To make the deleters compatible so that I can assign unique_ptr<T, empty_deleter<T>>
to an array of unique_ptr<T, deleter<allocator<T>>>
pointers...
I know there are converting constructors within the unique_ptr
implementation so in theory, the deleter of one type can be assinged to the unique_ptr
being declared with another type but there is a constraint these deleters shall be convertible somehow... could you please advice me how to reach that?
Additionally - once I am successfull in assigning the deleter instance of empty_deleter<T>
into unique_ptr<T, deleter<allocator<T>>>
whatever how, which operator()
is going to be called once the deletion is triggered? The one from empty_deleter<T>
or from deleter<allocator<T>>
?
As @Nicol Bolas points out, "object owned by such unique_ptr<T, empty_deleter<T>>
" is nonsensical. I will answer "how to make a smart pointer that sometimes owns and sometimes doesn't own it's pointee".
None of std::unique_ptr<T, empty_deleter<T>>
, std::unique_ptr<T, deleter<allocator<T>>>
, nor std::unique_ptr<T, deleter<other_allocator<T>>>
are assignable to one another.
If you want to mix and match ownerships of your pointers, you will have to type-erase the deleter. The simplest way is to use the existing function-object type-erasure type, std::function
.
template <typename T>
class pmr_unique_ptr : public std::unique_ptr<T, std::function<void(T *)>> {
public:
using unique_ptr::unique_ptr;
// have to supply a deleter
pmr_unique_ptr(pointer) = delete;
pmr_unique_ptr() = delete;
pmr_unique_ptr(std::nullptr_t) = delete;
};
This can be constructed from std::unique_ptr<T, D>
so long as D
is copyable.