【发布时间】:2019-07-26 13:49:08
【问题描述】:
我在这里看到了这个问题的许多变体,但我仍然觉得我的具体情况有所不同。
我的目标是封装一个如下所示的 C API:
TF_Buffer* buf = TF_AllocateBuffer();
// ...
TF_DeleteBuffer(buf);
由于我有许多这样的对象,我很想创建一个名为handle 的泛型类型,它可以保存给定的指针并在销毁时调用适当的释放器。我想象的用例是
class buffer : public handle<TF_Buffer, TF_DeleteBuffer> {
public:
buffer(TF_Buffer* b): handle(b) {}
}
不幸的是,由于TF_DeleteBuffer 是一个简单的函数(void TF_DeleteBuffer(TF_Buffer*) 类型),我无法让它工作。我确实设法解决了为函数创建函数对象的问题,所以以下确实有效
template<typename Obj, typename Deleter>
class handle {
public:
Obj* obj;
handle(Obj* o): obj(o) {};
~handle() { if (obj) Deleter()(obj); }
};
struct buffer_deleter {
void operator()(TF_Buffer* b) { TF_DeleteBuffer(b); }
};
class buffer : public handle<TF_Buffer, buffer_deleter> {
public:
buffer(TF_Buffer* b): handle(b) {}
}
但是为了这个目的而定义buffer_deleter 类感觉很脏。我想这样的事情应该可以工作(有或没有std::function)
template<typename Obj, std::function<void(Obj*)> Deleter>
class handle {
// ...
}
但我找不到让编译器满意的方法。据我了解,这有点类似于接受删除器类型对象的std::unique_ptr,而std::shared_ptr 接受删除器函数指针并将其存储在共享对象中。我不介意显式存储指针(并使用额外的内存),但同时,考虑到我将创建很多这些类型,我想有一些方法让它在语法上很好。我真的不想将删除器指针传递给正在创建的对象的每个实例,这就是我试图将它隐藏在模板中的原因。
【问题讨论】:
-
我最近遇到了这个问题,我的结论是“不”。我很确定您的工作解决方案是 the 使用的解决方案,
unique_ptr也有理由使用它。除了它还要求删除器的实例,而不是创建一个默认实例。 -
@akub Arnold 你能将类缓冲区声明为模板类吗?
-
删除器功能可以变化吗?如果没有,您可以只创建不带模板参数的
handle类并在其析构函数中调用TF_DeleteBuffer。 -
@VladfromMoscow 是的,我可以将缓冲区定义为任何东西,从那时起我就可以将专业化存储在一个合理的名称下
-
@MikeLischke "Obj" 和 "Deleter" 有许多不同的组合,所以这就是为什么
handle是通用的......我基本上想用 RAII 包装一大堆 C API
标签: c++ templates function-pointers