我正在尝试创建一个回调函数结构,我可以放置一个泛型函数和它将接收的所有参数,以便在执行期间我可以调用它。
对我而言,它看起来像这样:
template <typename T, typename... targs>
class CallbackFunction {
private:
targs... args;
std::function<T(targs...)> fun;
public:
CallbackFunction(std::function<T(targs...)> fun, targs... args) : fun(fun), args(args) {}
T call () {
return this->fun(this->args);
}
};
所以我可以这样做:
CallbackFunction cb = CallbackFunction(printf, "Hello World!\n");
cb.call();
我知道这样做有两个问题:
1-你无法存储targs ... args。编译器说data member type contains unexpanded parameter pack 'targs'
2-您无法按原样将args发送到该功能。你需要以某种方式解压缩它。编译器说expression contains unexpanded parameter pack 'args'
这样做的正确方法是什么?
答案 0 :(得分:2)
template<class T>
using CallbackFunction=std::function<T()>;
CallbackFunction<void> cb = []{printf("Hello World!\n");};
cb();
类型T
必须是类型的一部分,因此除非C ++ 17必须列出至少它。
targs...
只是一个内部细节。 std::function
会在签名上键入擦除,并可以处理存储任何targs...
或其他状态的集合。
可以调用并返回T
并存储某些状态的对象是std::function<T()>
。剩下的就是渣滓。
如果你真的必须
template <typename T>
class CallbackFunction {
std::function<T()> fun;
public:
template<class...targs>
CallbackFunction(std::function<T(targs...)> fun, targs... args) : fun([=]{ return fun(args...); }){}
T call() const {
return fun();
}
};
使用移动语义对此进行优化是一项更多的工作。查找std::apply
的实现:
template<class...targs>
CallbackFunction(std::function<T(targs...)> fun, targs... args) : fun(
[fun=std::move(fun), args=std::make_tuple(std::move(args)...)]()->decltype(auto){
return std::apply(fun,args);
}
){}