我有这段代码:
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
的类型是否可以安排callfn
模板/模板,使其可以从{{T
类型中推导出f
类型1}}?
答案 0 :(得分:2)
在aaronman的post之上添加。虽然你不能单独使用模板类,但有一些帮助程序,包括宏,它可能是:
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
(类型为T
)为特定类型f
创建void (*)(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
中推导出指向对象的类型。正如我所指出的,这可以用宏来完成,但我认为这不是一件好事,原因有两个:
mfree
(例如void mfree(MObj*)
和void mfree(Foo*)
)有不同的重载,则它不起作用。std::unique_ptr
的尖头类型,并且(最终)看到它的删除者。上面的第1行确实显示了类型(MObj
),但第2行没有。没有看到类型可能会让一些人感到困惑。我同意上面的第二点是有争议的(类似于 should-I-use-auto 辩论)。
答案 1 :(得分:1)
不需要知道结构或类的args只有函数在c ++中有模板类型推导。
论文n3602似乎解决了这个问题,所以看来你并不是唯一一个发现这种烦人的人(我也是)。我不知道它是否会被收录,但论文至少意味着其他人正在考虑它。 n6301将能够消除非类型模板参数的冗余类型名称。
另一件事(也在c ++ 14中)是make_unique
,它将在下一个标准中。编写自己也可能相对容易。
正如我在评论中指出的那样,目前还不清楚你究竟想要实现什么,如果必须写出额外的类型实际上是一个障碍。
由于您在评论中明确表示需要这样做才能为unique_ptr
做一个删除操作我不确定是什么问题。
std::unique_ptr<int,void(*)(int*)> ptr(int_ptr,deleter);