4

我有这个代码:

template <typename T, void (*f)(T*)>
class callfn
{
  public:
  void operator()(T* obj) const
  {
    f(obj);
  }
};

void call(int* foo) {}

void test()
{
  callfn<int, call> fun;
  fun(1);
}

这往往工作正常。然而,这种类型callfn到处都在使用,如果我可以这样称呼它,我会更喜欢

callfn<call> fun;

相反,在不修改类型的情况下是否可以以可以从类型推断类型的方式call排列模板/模板?callfnTf

4

2 回答 2

2

添加在aaronman帖子之上。尽管您不能单独使用模板类,但使用一些帮助程序(包括宏)是可能的:

template <typename T>
T deduce(void(*)(T*));

#define CALLFN(f) callfn<decltype(deduce(f)), f> 

使用示例:

CALLFN(call) fun; // instead of 'callfn<call> fun;' as asked

但是,从 OP 的评论来看,这只是一个问题的一部分,没有这一部分的解决方案似乎更简单。

如果我理解正确,您想使用自定义函数删除器(类型)std::unique_ptr为某种类型创建一个,但您不希望在. 例如,考虑:Tfvoid (*)(T*)std::unique_ptr

class MObj { /* ... */ };
void mfree(MObj*) { /* ... */ }

正如在 OP 的评论中所说,我们通常有

std::unique_ptr<MObj, void(*)(MObj*)> p1(nullptr, mfree);
assert(sizeof(p1) == sizeof(MObj*) * 2);

但使用callfn我们可以节省空间:

std::unique_ptr<MObj, callfn<MObj, mfree>> p2;
assert(sizeof(p2) == sizeof(MObj*));

我相信上述解决方案的唯一烦恼是需要输入callfn两次MObj。那么,这个呢:

template <typename T, void (*f)(T*)>
using light_unique_ptr = std::unique_ptr<T, callfn<T, f>>;

light_unique_ptr<MObj, mfree> p3; // 1
assert(sizeof(p3) == sizeof(MObj*));

我也明白(也许我错了)意图是更短的东西,比如

lighter_unique_ptr<mfree> p4; // 2
assert(sizeof(p4) == sizeof(MObj*));

并让编译器从mfree. 正如我所指出的,这可以通过宏来完成,但我认为这不是一件好事,原因有两个:

  1. mfree如果我们对(比如void mfree(MObj*)和)有不同的重载,它就不起作用void mfree(Foo*)
  2. 用户通常希望std::unique_ptr在其实例化中看到指向的 a 类型,并(最终)看到它的删除器。上面的第 1 行确实显示了类型 ( MObj),但第 2 行没有。看不到类型可能会让某些人感到困惑。

我同意上面的第二点是有争议的(类似于我应该使用汽车的辩论)。

于 2013-11-08T06:38:24.520 回答
1

不,您需要知道结构或类的参数,只有函数在 C++ 中具有模板类型推导。

论文n3602似乎解决了这个问题,所以看起来你不是唯一一个觉得这很烦人的人(我也是)。我不知道它是否会被包括在内,但这篇论文至少意味着其他人正在考虑它。n6301将能够消除非类型模板参数的冗余类型名。

另一件事(也在 c++14 中)是make_unique下一个标准中的内容。自己编写代码也可能相对容易。

正如我在评论中指出的那样,目前尚不清楚您究竟想通过此实现什么,以及是否必须编写额外的类型实际上是一个障碍。

由于您在评论中明确表示您需要这个来删除 aunique_ptr我不确定有什么问题。

std::unique_ptr<int,void(*)(int*)> ptr(int_ptr,deleter);
于 2013-11-08T05:28:10.100 回答