Sté*_*ane 2 c++ lambda unique-ptr c++17 tensorrt
诸如nvinfer1::IRuntime和 的NVIDIA TensorRT 对象nvinfer1::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>>;
Run Code Online (Sandbox Code Playgroud)
而不是std::unique_ptr<T>,然后使用NVIDIAUniquePtr<T>.
到目前为止,这工作正常。然后我在清理代码时尝试做的是用 lambda 替换删除器,这样我就可以跳过定义NVIDIADestroyer结构。但我无法弄清楚如何做到这一点。我的想法是这样的:
template<typename T>
using NVIDIAUniquePtr = std::unique_ptr<T, [](T * t)
{
t->destroy();
}>;
Run Code Online (Sandbox Code Playgroud)
但这会导致以下错误消息:
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
}>;
^
Run Code Online (Sandbox Code Playgroud)
有没有办法使这项工作?
使用定义为 astruct或class自 C++11 以来零运行时间和空间开销的无状态删除器,没有比这更好的了。
使用函数模板而不是删除器的类模板消除了指定删除器类模板参数以及必须包含 CUDA 头文件的需要。
noexcept在删除器函数上可能会导致更小的调用代码。因为在调用者周围noexcept调用中不需要编译器生成的堆栈展开代码。(GNU C++ 标准库~unique_ptr()是noexcept无条件的,但 C++ 标准并不要求这样做。GNU C++ 标准库可能会为您做到这一点,这正是我所说的原因。太糟糕noexcept了,出于 ABI 稳定性的原因,编译器没有自动推断和应用(#1 我们不能在 C++ 中拥有好东西的原因),理论上可以用明确的用户提供的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';
}
Run Code Online (Sandbox Code Playgroud)
编译-std=c++17输出:
8
8
8
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
195 次 |
| 最近记录: |