Обратные вызовы в C++ | страница 52



4.6.3. Преобразование с настройкой сигнатуры

В п. 4.2.2 реализованы объекты преобразования, которые работали с фиксированной сигнатурой. Используя технику, описанную в Листинг 47 п. 4.5.2, модифицируем их таким образом, чтобы сигнатуру можно было настроить. Для этого в параметрах шаблона вместо задания типов указателей на функцию будем задавать параметры, определяющие сигнатуру, а типы указателей будем выводить из этих параметров.

Рассмотрим вначале указатели на функцию (Листинг 54).

Листинг 54. Преобразование вызовов с настройкой сигнатуры для указателей на функцию

>template  // (1)

>class CallbackConverter;


>template  // (2)

>class CallbackConverter               // (3)

>{

>public:


>  using Function = Return(*)(Context, ArgumentList…);  // (4)


>  CallbackConverter(Function argFunction = nullptr, Context argContext = nullptr)  // (5)

>  {

>    ptrFunction = argFunction; context = argContext;

>  }


>  Return operator() (ArgumentList… arguments)                 // (6)

>  {

>    ptrFunction(context, arguments…);                         // (7)

>  }

>private:

>  Function ptrFunction;  // (8)

>  Context context;       // (9)

>};


В строке 1 вводится общая специализация шаблона. В строке 2 объявляется специализация для указателей на функцию, в которой задается тип передаваемого контекста и параметры сигнатуры. В строке 4 выводится тип указателя. В конструкторе 5 осуществляется настройка указателей. В перегруженном операторе 6 осуществляется вызов 7, в который передаются соответствующие аргументы.


Аналогично выполняется специализация для вызова методов класса (Листинг 55).

Листинг 55. Преобразование вызовов с настройкой сигнатуры для указателей на метод класса.

>template  // (1)

>class CallbackConverter          // (2)

>{

>public:


>  using MemberPointer = Return(ClassType::*)(ArgumentList…);  // (3)


>  CallbackConverter(MemberPointer methodPointer = nullptr, ClassType* classPointer = nullptr)  // (4)

>  {

>      ptrClass = classPointer; ptrMethod = methodPointer;

>  }


>  Return operator()(ArgumentList… arguments)  // (5)

>  {

>    (ptrClass->*ptrMethod)(arguments…);       // (6)

>  }

>private:

>  ClassType* ptrClass;                          // (7)

>  MemberPointer ptrMethod;                      // (8)

>};


Реализация практически повторяет предыдущую, за исключением того, что в объявлениях типов сигнатуры добавляется класс (строки 2 и 3), а перегруженный оператор вызывает метод класса (строка 6).