使用typedef为std::unique_ptr指定自定义默认删除器

5

我有一些关于IT技术的内容需要翻译,涉及到C语言编写的代码和相关资源。其中包含以下函数:

ResourcePointer resource_new(void);
void resource_delete(ResourcePointer *res);

其中ResourcePointer是什么

typedef void * ResourcePointer;

我想为 std::unique_ptr 创建一个 typedef,指定自定义默认删除器。
下面的代码可以工作,但需要重复使用 resource_delete
typedef std::unique_ptr<std::remove_pointer<ResourcePointer>::type, 
                            void(*)(ResourcePointer)> Resource_auto_pointer;

并且在代码后面

Resource_auto_pointer resource(resource_new(), resource_delete);
...
Resource_auto_pointer res2 = { resource_new(), resource_delete };

我应该如何更改 typedef,以便编译器在需要时自动替换 resource_delete? 我希望我的代码像下面这样

Resource_auto_pointer2 resource (resource_new());
...
Resource_auto_pointer2 res2 = { resource_new() };

编译器应该想办法猜到它应该为每个类型为 Resource_auto_pointer2 的对象调用 resource_delete。
我在 MS Visual Studio 2013 中工作。
更新: 我已经阅读了其他类似问题的答案。 有两件事我不明白。 1.为什么 std::function 不起作用? 2.既然(可能)一切都已经说过了,为什么我需要创建新的类型?

1
定义自己的函数 std::unique_ptr<void, void(&)(void*)> make_resource() { return std::unique_ptr<void, void(&)(void*)>(resource_new(), resource_delete); }示例 - Kerrek SB
可能是std::unique_ptr、删除器和Win32 API的重复问题。 - legends2k
3个回答

6

定义一个函数对象,调用正确的函数:

struct resource_deleter
{
  using pointer = std::remove_pointer<ResourcePointer>::type;
  void operator()(ResourcePointer p) const { resource_delete(p); }
};

using res_ptr = std::unique_ptr<resource_deleter::pointer, resource_deleter>;

现在你不需要将删除器传递给unique_ptr构造函数,因为可以默认构造删除器并且它会自动处理正确的事情:

res_ptr p{ resource_new() };

1

使用Lambda表达式,包括在C++20中的未求值上下文中的Lambda表达式:

#include <iostream>
#include <memory>
#include <type_traits>

using HANDLE = std::byte*;

HANDLE make_HANDLE() { static auto k_h = HANDLE{}; return ++k_h; } // AKA Win32's CreateFile etc
void close_HANDLE(HANDLE h) { std::cout << "HANDLE_close(" << h << ")" << std::endl; } // AKA Win32's CloseHandle etc

#if __cplusplus >= 202002 // C++20; using lambda in unevaluated context
using HANDLE_ptr = std::unique_ptr<
    std::remove_pointer_t<HANDLE>,
    decltype([](HANDLE h) { close_HANDLE(h); })>;
#else
[[maybe_unused]] inline static auto HANDLE_deleter = [](HANDLE h) { close_HANDLE(h); };
using HANDLE_ptr = std::unique_ptr<std::remove_pointer_t<HANDLE>, decltype(HANDLE_deleter)>;
#endif

int main()
{
    auto h1 = HANDLE_ptr(make_HANDLE());
    auto h2 = HANDLE_ptr(make_HANDLE());
    auto h3 = HANDLE_ptr(make_HANDLE());
    std::cout << h1 << std::endl;
    std::cout << h2 << std::endl;
    std::cout << h3 << std::endl;
}

0
我已经找到了我的问题的答案。std::unique_ptr在实例化时需要类型,而resource_delete函数的地址是一个常量。需要创建一个structclass将其转换为类型。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接