我可以用自定义删除器简洁地声明 std::unique_ptr 吗?
Can I succintly declare std::unique_ptr with custom deleter?
我正在处理具有关联的 new_
和 free_
方法的 C 类型。
new_
的类型签名可能不同,但 free_
始终是 void free_something(something*);
目前,我正在以这种方式声明我的 unique_ptr
,这似乎过于冗长:
std::unique_ptr<qdr_link_t, decltype(&free_qdr_link_t)> link{new_qdr_link_t(), free_qdr_link_t};
不知何故,我可以用更少的仪式来做这件事吗?当我的释放器是 std::free()
函数时,我在 处看到了一个巧妙的解决方案。我试图创建一个可以参数化解除分配器的版本,但我一无所获。
我能想到的最好办法是从上面的声明中创建一个宏。
我一直在使用以下内容:
template <auto fptr>
struct Caller {
template <class... Args>
auto
operator()(Args&&... args) noexcept
{
return fptr(std::forward<Args...>(args)...);
}
};
用法示例:
using qdr_freer = Caller<free_qdr_link_t>;
using unique_qdr_ptr = std::unique_ptr<qdr_link_t, qdr_freer>;
[[nodiscard]] unique_qdr_ptr
make_qdr_unique()
{
return unique_qdr_ptr{new_qdr_link_t()};
}
尽管此实现使用了 C++17 功能,因此需要进行一些更改才能在 C++11 中使用。
请注意,虽然 Caller
看起来很适合 std::free
,但严格来说它们是不兼容的,因为 std::free
是一个未指定为“可寻址”的标准库函数。
让语言来完成艰苦的工作!
#include <memory>
struct qdr_link_t;
qdr_link_t* new_qdr_link_t();
void free_qdr_link_t(qdr_link_t*);
template <typename T, typename Deleter>
auto make_unique_ptr(T* raw, Deleter deleter)
{
return std::unique_ptr<T, Deleter>(raw, deleter);
}
//std::unique_ptr<qdr_link_t, decltype(&free_qdr_link_t)> link{new_qdr_link_t(), free_qdr_link_t};
auto link = make_unique_ptr(new_qdr_link_t(), free_qdr_link_t);
添加 std::forward
调味(如果您喜欢)。
对于 C++11,您需要将尾部 return 类型 -> std::unique_ptr<T, Deleter>
添加到 make_unique_ptr
,或者将其放入“正常”return类型。
我正在处理具有关联的 new_
和 free_
方法的 C 类型。
new_
的类型签名可能不同,但 free_
始终是 void free_something(something*);
目前,我正在以这种方式声明我的 unique_ptr
,这似乎过于冗长:
std::unique_ptr<qdr_link_t, decltype(&free_qdr_link_t)> link{new_qdr_link_t(), free_qdr_link_t};
不知何故,我可以用更少的仪式来做这件事吗?当我的释放器是 std::free()
函数时,我在 处看到了一个巧妙的解决方案。我试图创建一个可以参数化解除分配器的版本,但我一无所获。
我能想到的最好办法是从上面的声明中创建一个宏。
我一直在使用以下内容:
template <auto fptr>
struct Caller {
template <class... Args>
auto
operator()(Args&&... args) noexcept
{
return fptr(std::forward<Args...>(args)...);
}
};
用法示例:
using qdr_freer = Caller<free_qdr_link_t>;
using unique_qdr_ptr = std::unique_ptr<qdr_link_t, qdr_freer>;
[[nodiscard]] unique_qdr_ptr
make_qdr_unique()
{
return unique_qdr_ptr{new_qdr_link_t()};
}
尽管此实现使用了 C++17 功能,因此需要进行一些更改才能在 C++11 中使用。
请注意,虽然 Caller
看起来很适合 std::free
,但严格来说它们是不兼容的,因为 std::free
是一个未指定为“可寻址”的标准库函数。
让语言来完成艰苦的工作!
#include <memory>
struct qdr_link_t;
qdr_link_t* new_qdr_link_t();
void free_qdr_link_t(qdr_link_t*);
template <typename T, typename Deleter>
auto make_unique_ptr(T* raw, Deleter deleter)
{
return std::unique_ptr<T, Deleter>(raw, deleter);
}
//std::unique_ptr<qdr_link_t, decltype(&free_qdr_link_t)> link{new_qdr_link_t(), free_qdr_link_t};
auto link = make_unique_ptr(new_qdr_link_t(), free_qdr_link_t);
添加 std::forward
调味(如果您喜欢)。
对于 C++11,您需要将尾部 return 类型 -> std::unique_ptr<T, Deleter>
添加到 make_unique_ptr
,或者将其放入“正常”return类型。