如何在不使用C ++创建函数对象的情况下将函数指针作为模板值参数传递?

Jak*_*old 4 c++ templates function-pointers

我在这里已经看到了这个问题的许多变体,但是我仍然觉得我的具体情况有所不同。

我的目标是包装一个如下所示的C API:

TF_Buffer* buf = TF_AllocateBuffer();
// ...
TF_DeleteBuffer(buf);
Run Code Online (Sandbox Code Playgroud)

由于我有许多这样的对象,因此我很想创建一个名为的通用类型handle,该类型可以容纳给定的指针,并在销毁时调用适当的释放器。我想象的用例是

class buffer : public handle<TF_Buffer, TF_DeleteBuffer> {
public:
  buffer(TF_Buffer* b): handle(b) {}
}
Run Code Online (Sandbox Code Playgroud)

不幸的是,由于这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) {}
}
Run Code Online (Sandbox Code Playgroud)

但是buffer_deleter仅为此目的而定义类感觉很脏。我想像这样的东西应该工作(带或不带std::function

template<typename Obj, std::function<void(Obj*)> Deleter>
class handle {
  // ...
}
Run Code Online (Sandbox Code Playgroud)

但我找不到使编译器满意的方法。据我了解,这有点类似于std::unique_ptr接受删除器类型对象,与std::shared_ptr接受删除器函数指针并将其存储在共享对象中。我不介意显式存储指针(并使用额外的内存),但是与此同时,鉴于我将创建许多此类,我希望有某种方法使其在语法上更美观。我真的不想将删除器指针传递给正在创建的对象的每个实例,这就是为什么我试图将其隐藏在模板中。

son*_*yao 6

您可以将非类型模板参数定义为函数指针。

template<typename Obj, void(*Deleter)(Obj*)>
class handle {
public:
  Obj* obj;

  handle(Obj* o): obj(o) {};
  ~handle() { if (obj) Deleter(obj); }
};
Run Code Online (Sandbox Code Playgroud)

并像这样使用

class buffer : public handle<TF_Buffer, &TF_DeleteBuffer> {
  ...
};
Run Code Online (Sandbox Code Playgroud)