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

multiple specializations of a variadic template with a statically bound member function pointer?

本文关键字:专业化 成员 静态绑定 函数 指针      更新时间:2023-10-16

在一个可变模板的参数之一是静态绑定的成员函数指针的情况下,是否可以对其进行多次专门化?

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

我在下面的代码中传递了一个成员函数指针作为模板参数,由于函数指针是一个在编译时已知的常量,我希望优化器能够通过函数指针边界进行工作。

我已经创建了两个委托,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 worldn";
  }
  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的签名中推导出来的

我意识到成员函数指针不是一种类型,但就像你可以传递一个特定的整数作为模板参数(元编程中使用的模板递归)一样,我认为你可以有一个特定成员函数指针作为参数,从而允许静态绑定到该函数。

我追求的是可能的吗?如果没有,以上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;
};

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

template <typename T, T value>
struct Delegate;

然后将其专门化为成员函数对象(对每个cv限定符执行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;

或者,你可以使用我的function_traits类,它可以直接从T中提取R、C和A…,所以你不需要专门化,但仍然需要decltype和重复该方法。