c++ - 可变模板参数顺序问题
问题描述
我有一个模板化的函数包装器,我正在尝试将其更新为 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)...);
}
wherefun
是类型的指针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
.