Обратные вызовы в C++ | страница 74
Пример использования распределителя приведен в Листинг 78.
>struct FO
>{
> int operator() (int eventID) { return 10; }
> int callbackHandler(int eventID) { return 0; }
>};
>struct SResult
>{
> unsigned int code;
> const char* description;
>};
>SResult ExternalHandler(int eventID)
>{
> return SResult{ 1, "this is an error" };
>}
>int main()
>{
> FO fo;
> int eventID = 0;
> auto lambda = [](int eventID) { return 0.0; };
> auto callbackToMethod = std::bind(&FO::callbackHandler, fo, std::placeholders::_1);
> StaticDistributorReturn distributor(ExternalHandler, fo, callbackToMethod, lambda); // (1)
> auto [resExtHandler, resFoOperator, resFoMethod, resLambda] = distributor(eventID); // (2)
>}
В строке 1 объявляется распределитель, в конструктор передаются объекты вызова. Через перегруженный оператор 2 производятся вызовы хранимых объектов, результаты возвращаются с помощью структурных привязок.
К сожалению, мы не можем использовать рассмотренную реализацию для объектов, которые не возвращают результатов. Это связано с тем, что результаты выполнения вызовов возвращаются через кортеж, а он не может хранить типы void. Для таких вызовов нужно использовать реализацию, рассмотренную в предыдущем параграфе.
5.5.3. Параметризация возвращаемого значения
Итак, у нас имеется отдельная реализация распределителя для случая, когда результаты вызовов не требуются, и отдельная реализация для случая, когда необходимо получать возвращаемые значения. Обе реализации одинаковы, за исключением перегруженного оператора. Как сделать общую реализацию для обеих случаев? Разместить два перегруженных оператора в одном классе не получится, потому что они различаются только типом возвращаемого значения. Можно предложить следующее решение: ввести в шаблон дополнительный параметр, который указывает, нужно ли возвращать результаты выполнения вызовов, и в зависимости от этого по-разному формировать перегруженный оператор с помощью условной компиляции. Реализация приведена в Листинг 79.
>template
>class StaticDistributor
>{
>public:
> StaticDistributor(CallObjects… objects) : callObjects(objects…) {} // (2)
> auto& tuple() { return callObjects; } // (3)
> template
> auto operator() (CallData… callData) // (4)
> {
>#define callObject std::get<0>(callObjects) // (5)