为了账号安全,请及时绑定邮箱和手机立即绑定

“解压缩”元组以调用匹配的函数指针

“解压缩”元组以调用匹配的函数指针

C++ C
Qyouu 2019-06-03 17:03:05
“解压缩”元组以调用匹配的函数指针我试着储存在std::tuple不同数量的值,这些值稍后将用作调用与存储类型匹配的函数指针的参数。我创建了一个简单的示例,展示了我正在努力解决的问题:#include <iostream>#include <tuple>void f(int a, double b, void* c) {   std::cout << a << ":" << b << ":" << c << std::endl;}template <typename ...Args>struct save_it_for_later {   std::tuple<Args...> params;   void (*func)(Args...);   void delayed_dispatch() {      // How can I "unpack" params to call func?      func(std::get<0>(params), std::get<1>(params), std::get<2>(params));      // But I *really* don't want to write 20 versions of dispatch so I'd rather       // write something like:      func(params...); // Not legal   }};int main() {   int a=666;   double b = -1.234;   void *c = NULL;   save_it_for_later<int,double,void*> saved = {                                  std::tuple<int,double,void*>(a,b,c), f};   saved.delayed_dispatch();}正常情况下涉及的问题std::tuple或者是各种模板,我会编写另一个模板,如template <typename Head, typename ...Tail>一个地递归地计算所有类型,但是我看不出有什么方法来分配函数调用。这样做的真正动机要复杂一些,而且基本上只是一个学习练习。您可以假设我是从另一个接口通过契约传递元组的,所以不能更改,但是将其解压缩到函数调用中的愿望是我的愿望。这排除了使用std::bind作为规避潜在问题的廉价方法。使用std::tuple,还是另一种更好的方法来实现相同的净结果:存储/转发一些值和一个函数指针,直到一个任意的未来点?
查看完整描述

3 回答

?
拉莫斯之舞

TA贡献1820条经验 获得超10个赞

您需要构建一个数字参数包并解压它们。

template<int ...>struct seq { };template<int N, int ...S>struct gens : gens<N-1, N-1, S...> { };template<int ...S>struct gens<0, S...> {
  typedef seq<S...> type;};// ...
  void delayed_dispatch() {
     callFunc(typename gens<sizeof...(Args)>::type());
  }

  template<int ...S>
  void callFunc(seq<S...>) {
     func(std::get<S>(params) ...);
  }// ...


查看完整回答
反对 回复 2019-06-03
?
守着星空守着你

TA贡献1799条经验 获得超8个赞

这里是一个C+14解决方案。

template <typename ...Args>struct save_it_for_later{
  std::tuple<Args...> params;
  void (*func)(Args...);

  template<std::size_t ...I>
  void call_func(std::index_sequence<I...>)
  { func(std::get<I>(params)...); }
  void delayed_dispatch()
  { call_func(std::index_sequence_for<Args...>{}); }};

这仍然需要一个助手函数(call_func)。由于这是一个常见的成语,也许标准应该直接支持它std::call可能的实施

// helper classtemplate<typename R, template<typename...> class Params, typename... Args, std::size_t... I
>R call_helper(std::function<R(Args...)> const&func, Params<Args...> const&params, std::index_sequence<I...>)
{ return func(std::get<I>(params)...); }// "return func(params...)"template<typename R, template<typename...
> class Params, typename... Args>R call(std::function<R(Args...)> const&func, Params<Args...> const&params)
{ return call_helper(func,params,std::index_sequence_for<Args...>{}); }

那么我们的延迟调度就变成了

template <typename ...Args>struct save_it_for_later{
  std::tuple<Args...> params;
  std::function<void(Args...)> func;
  void delayed_dispatch()
  { std::call(func,params); }};


查看完整回答
反对 回复 2019-06-03
  • 3 回答
  • 0 关注
  • 510 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信