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

发布于 2024-12-28 03:43:30 字数 2205 浏览 0 评论 0原文

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

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

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

我创建了 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 的签名。

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

我所追求的可能吗? 如果不行的话,上面的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;
};

Is it possible to have multiple specializations of a variadic template where one of the template parameters is a statically bound member function pointer?

I'm attempting to build a delegate where the callback function is a compile time constant - thereby aiding the optimizer to see past the function pointer boundary.

I have the following code where I pass a member function pointer as a template parameter, and since the function pointer is a constant which is known at compile-time, my expectation is that the optimizer will be able to work through the function pointer boundary.

I have created 2 delegates, delegate0 and delegate1, which are for member functions which have 0 and 1 arguments respectively.

#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();
}

However, I would like to improve on this in 2 ways:

  1. All permutations of the number of arguments to be specializations of a variadic delegate template.
  2. Use template argument deduction such that declaring something like delegate<&app::cb> (when cb is not ambiguous), class_t, mem_func_t, arg0, arg1, etc... are all deduced from the signature for app::cb.

I realize that a member function pointer is not a type, but just like you can pass a particular integer as a template parameter (ala template recursion used in metaprogramming), I figure you can have a specific member function pointer as a parameter - thereby allowing static binding to that function.

Is what I'm after even possible?
If not, is either of 1 or 2 above possible?
I would really appreciate a working example, because I've been banging my head against my keyboard with no success as of yet.

I have the following miserable attempt. It is clearly not what I'm looking for, but in order to show the direction I've been heading, I thought it perhaps useful to include.

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;
};

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

下雨或天晴 2025-01-04 03:43:30

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

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 并重复该方法。

Declare a template taking any types:

template <typename T, T value>
struct Delegate;

and then specialize it for member function objects (do it 4 times for each cv-qualifier):

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... .
};

As I've answered before, you'll need decltype:

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

Alternatively, you could use my function_traits class which can extract the R, C and A... from T directly so you don't need to specialize, but decltype and repeating the method is still needed.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文