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



Листинг 82. Возврат значений для динамического набора получателей

>template 

>class DynamicDistributor

>{

>  /**********************……**********************************/


>  template  // (1)

>  void operator()(CallbackReturn callbackReturn, ArgumentList… arguments)

>  {

>    for (auto& callObject : callObjects)

>    {

>        callbackReturn(callObject(arguments…));  // (2)

>    }

>  }

>private:

>  std::list< std::function > callObjects;

>};


Реализация совпадает с Листинг 82 п. 5.6.1, только добавляется еще один перегруженный оператор. Его шаблон объявлен строке 1, параметром шаблона является тип аргумента, через который будет выполняться обратный вызов. В строке 2 происходит вызов объекта, результат возвращается через аргумент, переданный как входной параметр функции.


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

Листинг 83. Распределение вызовов для динамического набора получателей

>struct FO

>{

>  int operator() (int eventID) { return 10; }

>  int callbackHandler(int eventID) { return 100; }

>};


>int ExternalHandler(int eventID)

>{

>  return 0;

>}


>int main()

>{

>  int eventID = 0;


>  FO fo;

>  auto lambda = [](int eventID) { return 0; };

>  auto binding = std::bind(&FO::callbackHandler, fo, std::placeholders::_1);


>  DynamicDistributor distributor;       // (1)


>  distributor.addCallObject(fo);                  // (2)

>  distributor.addCallObject(ExternalHandler);     // (3)

>  distributor.addCallObject(binding);             // (4)

>  distributor.addCallObject(lambda);              // (5)


>  distributor(eventID);                           // (6)


>  auto onReturnValue = [](int callResult) {};     // (7)

>  distributor(onReturnValue, eventID);            // (8)

>}


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


Касательно модификации содержимого контейнера наш распределитель поддерживает только одну операцию – добавление получателя. Ни удаление, ни модификация получателей не поддерживается. Это связано с тем, что получатели не идентифицированы, и поэтому невозможно узнать, в каком элементе контейнера хранится соответствующий объект вызова