несколько специализаций шаблона с статически связанным указателем на функцию-член? - PullRequest
1 голос
/ 22 января 2012

Можно ли иметь несколько специализаций вариационного шаблона, где один из параметров шаблона является статически связанным указателем на функцию-член?

Я пытаюсь создать делегат, в котором функция обратного вызова является временем компиляции.константа - тем самым помогает оптимизатору видеть за границей указателя функции.

У меня есть следующий код, в котором я передаю указатель на функцию-член в качестве параметра шаблона, и поскольку указатель на функцию является константой, известной при компиляции- время, я ожидаю, что оптимизатор сможет работать через границу указателя функции.

Я создал 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;
};

1 Ответ

1 голос
/ 22 января 2012

Объявите шаблон, принимающий любые типы:

template <typename T, T value>
struct Delegate;

, а затем специализируйте его для объектов-членов (сделайте это 4 раза для каждого cv-квалификатора):

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 , который может извлекать R, C и A ...от T напрямую, так что вам не нужно специализироваться, но decltype и повторение метода все еще необходимы.

...