Обратные вызовы в C++ | страница 33
> }
> void operator()(int eventID) // (5)
> {
> ptrClass->*ptrMethod)(eventID); // (6)
> }
>private:
> ClassName* ptrClass; // (7)
> ClassMethod ptrMethod; // (8)
>};
В строке 1 объявлен шаблон с параметром – именем класса. В строке 2 объявлена специализация шаблона из Листинг 27. Именно эта специализация будет выбрана компилятором, если шаблон инстанциируется указателем на метод класса и указателем на класс. В строке 3 объявлен тип – указатель на метод класса. Этот тип выводится из имени класса, поэтому в шаблоне одного параметра – имени класса – будет достаточно. В строке 4 объявляется конструктор, который будет сохранять требуемые значения – указатель на экземпляр класса и указатель на метод, переменные для хранения объявлены в строках 7 и 8. В строке 5 перегружается оператор вызова функции, который вызывает метод класса.
4.2.3. Исполнитель
Итак, определив объекты для преобразования вызовов, мы теперь можем использовать в шаблоне-инициаторе, определенном в Листинг 25 п. 4.2.1, любые типы аргументов обратного вызова. Пример приведен в Листинг 29.
>class Executor // (1)
>{
>public:
> static void staticCallbackHandler(int eventID, Executor* executor) {}
> void callbackHandler(int eventID) {}
> void operator() (int eventID) {}
>};
>void ExternalHandler(int eventID, void* somePointer)
>{
> Executor* ptrClass = (Executor*)somePointer;
>}
>int main()
>{
> Executor executor;
> int capturedValue = 0;
> // (2) External function
> using FunctionPointer = void(*)(int, void*);
> using FunctionConverter = CallbackConverter
> run(FunctionConverter(ExternalHandler, &executor));
> // (3) Static method
> using StaticPointer = void(*)(int, Executor*);
> using StaticConverter = CallbackConverter
> run(StaticConverter(Executor::staticCallbackHandler, &executor));
> // (4) Member merthod
> using MethodPointer = void(Executor::*)(int);
> using MethodConverter = CallbackConverter
> run(MethodConverter(&Executor::callbackHandler, &executor));
> // (5) Functional object
> run(executor);
> // (6) lambda-expression
> auto lambda = [capturedValue](int eventID) {/*it will be called by initiator*/};
> run(lambda);
>}
В строке 1 объявлен класс исполнителя, в котором определены все необходимые типы вызовов: статический метод, метод-член, перегруженный оператор. Для вызовов 2, 3 и 4 в качестве аргумента передается функциональный объект для преобразования, который инстанциируется соответствующими типами. В остальных случаях нужный аргумент передается непосредственно, преобразования вызовов там не нужно. При использовании лямбда-выражения (строка 6) компилятор неявно определит его тип и подставит его в функцию шаблона-инициатора как аргумент.