具有静态绑定成员函数指针的可变参数模板的多个特化?

时间:2012-01-22 18:58:27

标签: c++ delegates c++11 variadic-functions

是否可以对可变参数模板进行多次特化,其中一个模板参数是静态绑定的成员函数指针?

我正在尝试构建一个委托,其中回调函数是一个编译时常量 - 从而帮助优化器查看函数指针边界。

我有以下代码,我将成员函数指针作为模板参数传递,并且由于函数指针是一个在编译时已知的常量,我的期望是优化器将能够通过该函数指针边界。

我创建了2个委托,delegate0和delegate1,它们分别用于具有0和1参数的成员函数。

#include <iostream>

template<class class_t, void (class_t::*mem_func_t)()>
struct delegate0
{
  delegate0( class_t *obj_ )
      : _obj(obj_)
  { }

  void operator()()
  {
    (_obj->*mem_func_t)();
  }

 private:
  class_t *_obj;
};

template<class class_t, typename arg0, void (class_t::*mem_func_t)(arg0)>
struct delegate1
{
  delegate1( class_t *obj_, arg0 a0_ )
      : _obj(obj_)
      , _a0(a0_)
  { }

  void operator()()
  {
    (_obj->*mem_func_t)(_a0);
  }

 private:
  class_t *_obj;
  arg0 _a0;
};

struct app
{
  void cb()
  {
    std::cout << "hello world\n";
  }
  void cb1(int i)
  {
    std::cout << "hello world " << i << "\n";
  }
};

int main()
{
  app* foo = new app;

  delegate0<app, &app::cb> f(foo);
  f();

  delegate1<app, int, &app::cb1> f1(foo, 5);
  f1();
}

但是,我想以两种方式对此进行改进:

  1. 作为可变参数委托模板的特化的参数数量的所有排列。
  2. 使用模板参数推导,以便声明类似delegate<&app::cb>(当cb不含糊不清),class_t,mem_func_t,arg0,arg1等等时,都是从app::cb的签名中推断出来的。
  3. 我意识到成员函数指针不是一个类型,但就像你可以传递一个特定的整数作为模板参数(元编程中使用的ala模板递归),我想你可以有一个特定的成员函数指针作为参数 - 从而允许静态绑定到该函数。

    我追求甚至可能吗? 如果不是,可以是1或2中的任何一个吗? 我真的很感激一个有效的例子,因为我一直在用我的键盘撞击我的键盘而没有成功。

    我有以下悲惨的尝试。这显然不是我想要的,但为了显示我前进的方向,我认为包括它可能是有用的。

    template<typename...>
    struct delegate;
    
    template<class class_t, void (class_t::*mem_func_t)()>
    struct delegate<class_t, decltype(mem_func_t)> 
    {
      delegate( class_t *obj_ )
          : _obj(obj_)
      { }
    
      void operator()(mem_func_t f)
      {
        (_obj->*f)();
      }
    
      class_t *_obj;
    };
    
    template<class class_t, typename arg0, void (class_t::*mem_func_t)(arg0)>
    struct delegate<class_t, arg0, decltype(mem_func_t)>
    {
      delegate( class_t *obj_, arg0 a0_ )
          : _obj(obj_)
          , _a0(a0_)
      { }
    
      void operator()()
      {
        (_obj->*mem_func_t)(_a0);
      }
    
      class_t *_obj;
      arg0 _a0;
    };
    

1 个答案:

答案 0 :(得分:1)

声明采用任何类型的模板:

template <typename T, T value>
struct Delegate;

然后将其专门用于成员函数对象(为每个cv-qualifier做4次):

template <typename R, typename C, typename... A, R (C::* value)(A...) const>
struct Delegate<R(C::*)(A...) const, value>
{
   // do whatever you like with R, C, A... .
};

如前所述,您需要decltype

Delegate<decltype(&SomeClass::method), &SomeClass::method> del;

或者,您可以使用my function_traits class直接从T中提取R,C和A ...因此您不需要专门化,但是decltype仍然需要重复该方法。