Обратные вызовы в 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.

Листинг 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) компилятор неявно определит его тип и подставит его в функцию шаблона-инициатора как аргумент.