I am trying to reduce code duplication while using std::unique_ptr
and it's custom deleter.
I have the some containers Foo
, Bar
which are allocated using one custom allocator, so cannot be freed with delete
.
So the current code is:
struct UniqueFooDeleter
{
void operator()(Foo* foo)
{
internal_free(foo);
}
};
using unique_foo_ptr = std::unique_ptr<Foo, UniqueFooDeleter>;
struct UniqueBarDeleter
{
void operator()(Bar* bar)
{
internal_free(bar);
}
};
using unique_bar_ptr = std::unique_ptr<Bar, UniqueBarDeleter>;
I changed it to:
struct UniqueInternalDeleter
{
void operator()(Bar* bar)
{
internal_free(bar);
}
void operator()(Foo* foo)
{
internal_free(foo);
}
};
using unique_bar_ptr = std::unique_ptr<Bar, UniqueInternalDeleter>;
using unique_foo_ptr = std::unique_ptr<Foo, UniqueInternalDeleter>;
How can I do better such that any number of containers that are allocated via internal_free
can be used as std::unique_ptr
s ?
You can make the UniqueInternalDeleter
as templated functor and static_assert
, if the T
is not Foo
or bar
.
#include <type_traits> // std::is_same_v
template<typename T>
struct UniqueInternalDeleter /* final */
{
static_assert(std::is_same_v<T, Foo> || std::is_same_v<T, Bar>,
" T must be either Foo or Bar");
void operator()(T* barOrfoo)
{
internal_free(barOrfoo);
}
private:
void internal_free(T* barOrfoo)
{
if constexpr(std::is_same_v<T, Foo>)
// code for `Foo*`
else
// code for `Bar*`
}
};
This makes the your alias to be more specific for Bar
and Foo
:
using unique_bar_ptr = std::unique_ptr<Bar, UniqueInternalDeleter<Bar>>;
using unique_foo_ptr = std::unique_ptr<Foo, UniqueInternalDeleter<Foo>>;