我有一个模板化的函数包装器,我试图将其更新为C ++ 11语法(可变参数)。
我的问题是我被困在“ catch 22”中,其中“ Args...
”必须是最后一个模板参数,但同时不能在函数指针模板参数之后定义。
知道这是否可以解决吗?
template <typename... Args, void(*Function)(Args...)>
class function
{
public:
void operator ()(Args... args) const
{
(*Function)(std::forward<Args...>(args...));
}
};
答案 0 :(得分:0)
一种可能的方法是使用模板专业化
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
。