将 Vulkan 的 VkInstance 包装到 unique_ptr 中,无需额外的动态分配

Que*_*wer 1 c++ unique-ptr vulkan c++17

我正在尝试将 VkInstance (不透明指针)包装起来,unique_ptr但似乎我不能。

...
    VkInstance instance;
    if (vkCreateInstance(&createInfo, nullptr, &instance) != VK_SUCCESS) {
        throw std::runtime_error("failed to create vulkan instance");
    }

    auto del = [](VkInstance* p) {
        DBG("release vk instance");
        vkDestroyInstance(*p, nullptr);
    };
    auto ptr = std::unique_ptr<VkInstance, decltype(del)>(instance, del);
...
Run Code Online (Sandbox Code Playgroud)

错误:

no instance of constructor "std::unique_ptr<_Tp, _Dp>::unique_ptr [with _Tp=VkInstance, _Dp=lambda [](VkInstance *p)->void]" matches the argument list
Run Code Online (Sandbox Code Playgroud)

我不明白为什么。VkInstance 是一个指针,所以我传递它,删除器必须接受指向内存地址的指针,所以它仍然接收它,但类型仍然不匹配。

使用 make_unique取消引用它&并将其传递给 make_unique 会导致段错误。说得通。

我设法让它仅与额外的新调用一起工作的唯一方法,如下所示:

no instance of constructor "std::unique_ptr<_Tp, _Dp>::unique_ptr [with _Tp=VkInstance, _Dp=lambda [](VkInstance *p)->void]" matches the argument list
Run Code Online (Sandbox Code Playgroud)

但这是一个有点荒谬的解决方案,因为我动态分配一个应该位于 CPU 寄存器中并几乎立即传输到unique_ptr控制区域的东西。

那么,我可以在不进一步过度设计的情况下以某种方式实现我想要做的事情吗?

Nic*_*las 5

std::unique_ptr可以使用甚至不是指针的类型;它当然可以与不透明的指针类型一起使用,例如VkInstance. 但是,您必须知道如何按照预期的方式做事std::unique_ptr

关键点是:停止使用 lambda 表达式作为删除器。unique_ptr的删除器类型具有有用的功能,如果您使用 lambda 类型,则这些功能都无法使用。另外,如果你想使用函子类型的名称,那么必须做decltype一些练习而不是仅仅给它一个名称,这有点俗气。

所以制作一个合适的删除器:

struct VkInstanceDeleter
{
  using pointer = VkInstance;

  void operator()(VkInstance inst) {vkDestroyInstance(inst, nullptr);}
};

using InstPtr = std::unique_ptr<VkInstance, VkInstanceDeleter>;
Run Code Online (Sandbox Code Playgroud)

InstPtr现在可以用来管理VkInstance对象。唯一的问题是你不能使用->它,但无论如何这在 Vulkan 中没有意义。