c++ - 如何将 lambda 与模板化 std::unique_ptr 一起使用?

标签 c++ lambda c++17 unique-ptr tensorrt

NVIDIA TensorRT 对象,例如 nvinfer1::IRuntimenvinfer1::ICudaEngine不能直接存储在 std::unique_ptr<> 中。相反,他们有一个 destroy()必须调用的方法。

因此,要实现此目的,您必须使用如下删除器:

#include <NvInfer.h>
#include <cuda.h>

template<typename T>
struct NVIDIADestroyer
{
    void operator()(T * t)
    {
        t->destroy();
    }
};

template<typename T>
using NVIDIAUniquePtr = std::unique_ptr<T, NVIDIADestroyer<T>>;

而不是 std::unique_ptr<T> ,然后使用 NVIDIAUniquePtr<T> .

到目前为止,效果很好。然后我在清理代码时尝试做的就是用 lambda 替换删除器,这样我就可以跳过定义 NVIDIADestroyer结构。但我不知道该怎么做。我的想法是这样的:

template<typename T>
using NVIDIAUniquePtr = std::unique_ptr<T, [](T * t)
{
    t->destroy();
}>;

但这会导致以下错误消息:

TRT.hpp:52:45: error: lambda-expression in template-argument
using NVIDIAUniquePtr = std::unique_ptr<T, [](T * t)
                                             ^
TRT.hpp:55:2: error: template argument 2 is invalid
  }>;
  ^

有办法实现这个功能吗?

最佳答案

自 C++11 以来,使用定义为 structclass 的无状态删除器具有零运行时和空间开销,没有比这更好的了。

对删除器使用函数模板而不是类模板,无需指定删除器类模板参数,也无需包含 CUDA 头文件。

删除器函数上的

noexcept 可能会导致调用代码更小。因为在 noexcept 调用周围的调用者中不需要编译器生成的堆栈展开代码。 (GNU C++ 标准库 ~unique_ptr() 无条件地是 noexcept,但 C++ 标准并不要求这样做。GNU C++ 标准库可能会为您做到这一点,原因正是如此太糟糕了,出于 ABI 稳定性原因(我们在 C++ 中无法拥有好东西的第一个原因),编译器不会自动推导和应用 noexcept ,理论上可以用显式的用户提供的覆盖noexcept 规范,但这本身就是一个大主题。)

自 C++17 起,无捕获 lambda 闭包也可以用作零开销的删除器:

#include <memory>
#include <iostream>

// C++11
struct Deleter { template<class P> void operator()(P p) noexcept { p->destroy(); } };
template<class T> using P11 = std::unique_ptr<T, Deleter>;

// C++17
constexpr auto deleter = [](auto p) noexcept { p->destroy(); };
template<class T> using P17 = std::unique_ptr<T, decltype(deleter)>;

int main() {
    std::cout << sizeof(void*) << '\n';
    std::cout << sizeof(P11<void>) << '\n';
    std::cout << sizeof(P17<void>) << '\n';
}

使用 -std=c++17 编译输出:

8
8
8

关于c++ - 如何将 lambda 与模板化 std::unique_ptr 一起使用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65938991/

相关文章:

lambda - 在Scheme中使用map和lambda计算点积

c++ - 可以将c++运算符的功能名称制作为模板吗?

c++ - 为什么sv后缀引入的字符串不会过期?

c++ - 具有引用成员的结构是否具有唯一的对象表示?

c++ - CMake 用户构建的库;无法为目标指定链接库

c++ - 我的递归没问题吗?有没有破坏代码的例子?

c++ - 运行时对 cin 函数的困惑

scala - lambda () => 1 是否会在每次作为参数传递时在运行时创建对象?

c# - Lambda 内部的 Lambda

c++ - 修改cpp中的void指针