Обратные вызовы в C++ | страница 52
4.6.3. Преобразование с настройкой сигнатуры
В п. 4.2.2 реализованы объекты преобразования, которые работали с фиксированной сигнатурой. Используя технику, описанную в Листинг 47 п. 4.5.2, модифицируем их таким образом, чтобы сигнатуру можно было настроить. Для этого в параметрах шаблона вместо задания типов указателей на функцию будем задавать параметры, определяющие сигнатуру, а типы указателей будем выводить из этих параметров.
Рассмотрим вначале указатели на функцию (Листинг 54).
>template
>class CallbackConverter;
>template
>class CallbackConverter
>{
>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).
>template
>class CallbackConverter
>{
>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).