如何安全地重载 std::unique_ptr 的自定义删除器?
How can I safely overload custom deleter of std::unique_ptr?
我试图在使用 std::unique_ptr
和它的自定义删除器时减少代码重复。
我有一些容器 Foo
、Bar
是使用 one 自定义分配器分配的,因此无法使用 delete
释放。
所以当前代码是:
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>;
我改成了:
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>;
我怎样才能做得更好,以便通过 internal_free
分配的任意数量的容器都可以用作 std::unique_ptr
?
如果 T
不是 Foo
或 bar
.
,您可以将 UniqueInternalDeleter
作为模板仿函数和 static_assert
#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*`
}
};
这使得您的别名对于 Bar
和 Foo
更具体:
using unique_bar_ptr = std::unique_ptr<Bar, UniqueInternalDeleter<Bar>>;
using unique_foo_ptr = std::unique_ptr<Foo, UniqueInternalDeleter<Foo>>;
一种可能的方法:
template<class> struct needs_internal_free : std::false_type { };
struct unique_internal_deleter {
template<class T>
void operator()(T* ptr) const {
static_assert(needs_internal_free<T>::value);
internal_free(ptr);
}
};
template<class T>
using unique_internal_ptr = std::unique_ptr<T, unique_internal_deleter>;
现在我们可以声明具体类型了:
template<> struct needs_internal_free<Foo> : std::true_type { };
using unique_foo_ptr = unique_internal_ptr<Foo>;
template<> struct needs_internal_free<Bar> : std::true_type { };
using unique_bar_ptr = unique_internal_ptr<Bar>;
我试图在使用 std::unique_ptr
和它的自定义删除器时减少代码重复。
我有一些容器 Foo
、Bar
是使用 one 自定义分配器分配的,因此无法使用 delete
释放。
所以当前代码是:
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>;
我改成了:
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>;
我怎样才能做得更好,以便通过 internal_free
分配的任意数量的容器都可以用作 std::unique_ptr
?
如果 T
不是 Foo
或 bar
.
UniqueInternalDeleter
作为模板仿函数和 static_assert
#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*`
}
};
这使得您的别名对于 Bar
和 Foo
更具体:
using unique_bar_ptr = std::unique_ptr<Bar, UniqueInternalDeleter<Bar>>;
using unique_foo_ptr = std::unique_ptr<Foo, UniqueInternalDeleter<Foo>>;
一种可能的方法:
template<class> struct needs_internal_free : std::false_type { };
struct unique_internal_deleter {
template<class T>
void operator()(T* ptr) const {
static_assert(needs_internal_free<T>::value);
internal_free(ptr);
}
};
template<class T>
using unique_internal_ptr = std::unique_ptr<T, unique_internal_deleter>;
现在我们可以声明具体类型了:
template<> struct needs_internal_free<Foo> : std::true_type { };
using unique_foo_ptr = unique_internal_ptr<Foo>;
template<> struct needs_internal_free<Bar> : std::true_type { };
using unique_bar_ptr = unique_internal_ptr<Bar>;