我有一个模板化的函数包装器,我试图更新为C ++ 11语法(可变参数)。
我的问题是我遇到了“catch 22”,其中'Args...
'必须是最后一个模板参数,但同时,在函数指针模板参数之后无法定义。
知道这是否真的可以解决?
template <typename... Args, void(*Function)(Args...)>
class function
{
public:
void operator ()(Args... args) const
{
(*Function)(std::forward<Args...>(args...));
}
};
一种可能的方法是使用模板专门化
template <typename>
struct myFunc;
template <typename R, typename ... Args>
struct myFunc<R(*)(Args...)>
{
// ...
};
但是,这样,你拦截(作为模板参数)函数指针的类型,而不是函数指针本身;所以你必须以某种方式传递函数指针(构造函数?)。
还要注意,如果你想使用完美转发,你必须在接收参数作为通用引用的模板方法中转换operator()
(&&
)。
事情如下
template <typename ... As>
R operator() (As && ... args) const
{
return fun(std::forward<As>(args)...);
}
其中fun
是R(*)(Args...)
类型的指针。
以下是完整的编译示例
#include <iostream>
#include <utility>
int foo (int, long)
{ return 42; }
template <typename>
struct myFunc;
template <typename R, typename ... Args>
struct myFunc<R(*)(Args...)>
{
using funPnt = R(*)(Args...);
funPnt fun = nullptr;
myFunc (funPnt f0) : fun{f0}
{ }
template <typename ... As>
R operator() (As && ... args) const
{
return fun(std::forward<As>(args)...);
}
};
int main ()
{
myFunc<decltype(&foo)> mf0{&foo};
std::cout << mf0(1, 2l) << std::endl;
}
如果你真的希望指针函数作为模板参数(但是,这样,每个函数确定一个不同的类型;根据你的需要,这可能是好的或坏的),你可以在类型之前编写接收的myFunc
结构(相同的指针类型)然后是该类型的值。
所以
template <typename T, T>
struct myFunc;
template <typename R, typename ... Args, R(*Func)(Args...)>
struct myFunc<R(*)(Args...), Func>
{
template <typename ... As>
R operator() (As && ... args) const
{
return Func(std::forward<As>(args)...);
}
};
可以宣布
myFunc<decltype(&foo), foo> mf0;
如果你可以使用C ++ 17,你可以简化使用auto
作为模板值的类型;所以你可以避免这种类型
template <auto>
struct myFunc;
template <typename R, typename ... Args, R(*Func)(Args...)>
struct myFunc<Func>
{
template <typename ... As>
R operator() (As && ... args) const
{
return Func(std::forward<As>(args)...);
}
};
你可以按如下方式创建一个myFunc
对象
myFunc<&foo> mf0;
附录:如果你可以使用C ++ 17,你可以为第一个例子定义一个演绎指南(指针作为成员,而不是作为模板值参数)
template <typename R, typename ... Args>
myFunc (R(*)(Args...)) -> myFunc<R(*)(Args...)>;
所以,而不是
myFunc<decltype(&foo)> mf0{&foo};
你可以简单地写
myFunc mf0{&foo};
关闭主题:我希望你知道你正在重新发明轮子。正如NathanOliver所建议的那样,该标准提供了std::function
。