Обратные вызовы в C++ | страница 70
>void NativeHandler(int eventID)
>{
>}
>void ExternalHandler(int eventID, int contextID)
>{
>}
>struct FO
>{
> void operator() (int eventID, int contextID) {}
> void callbackHandler(int eventID, int contextID) {}
>};
>int main()
>{
> int eventID = 0, contextID = 0;
> FO fo;
> auto lambda = [](int eventID, int contextID) {};
> Distribute2(std::tuple( // (1)
> NativeHandler, // (2)
> std::bind(ExternalHandler, std::placeholders::_1, contextID), // (3)
> std::bind(&FO:: callbackHandler, fo, std::placeholders::_1, contextID), // (4)
> std::bind(&FO::operator(), fo, std::placeholders::_1, contextID), // (5)
> std::bind(lambda, std::placeholders::_1, contextID) // (6)
> ),
> eventID // (7)
> );
>}
Входными аргументами распределяющей функции служат кортеж объектов вызова (объявлен в строке 1) и данные вызова (строка 7). В строке 2 в кортеж передается объект вызова с сигнатурой, совпадающей с исходной. В строке 3 передается объект связывания (результат вызова std::bind), в котором исходный вызов перенаправляется в назначенную функцию ExternalHandler. В строке 4 объект связывания перенаправляет вызов в метод-член структуры, в строке 5 – в перегруженный оператор, в строке 6 – в лямбда-выражение.
5.4. Возврат результатов выполнения
5.4.1. Получение возвращаемых значений
До сих пор мы считали, что функции, реализующие код вызова, не возвращают результатов. Однако в некоторых случаях необходимо получить результаты выполнения вызовов. Очевидно, что в этом случае их должна вернуть распределяющая функция. Как же сформировать возвращаемые значение?
Поскольку возвращаемые значения могут иметь различные типы, напрашивается сохранять их в кортеже, который затем будет возвращаться как результат работы распределяющей функции. Но мы же не знаем заранее типы возвращаемых значений, их определяют объекты вызова. Какие тогда типы задавать при инстанциировании переменной-кортежа? Можно предложить следующее решение: при объявлении кортежа не указывать явно хранимые в нем типы, а в конструктор в качестве входных аргументов передать результаты выполнения вызовов. В этом случае типы элементов кортежа будут выведены автоматически.
Но сформировать набор результатов выполнения не так-то просто. Мы не можем перечислить в списке аргументов запрос объекта по индексу и его вызов, ведь количество объектов заранее не известно. Поэтому предварительно необходимо сформировать последовательность индексов, которая разворачивается в контексте запроса и вызова объекта. Реализация приведена в Листинг 73.