Обратные вызовы в C++ | страница 75
>#define callObjType decltype(callObject) // (6)
>#define callObjInstance std::declval
>#define testCall callObjInstance(callData…) // (8)
>#define retType decltype(testCall) // (9)
> //if constexpr (std::is_same_v
> if constexpr (std::is_same_v
> return Distribute2(callObjects, callData…); // (12)
> else
> return DistributeReturn(callObjects, callData…); // (13)
> }
>private:
> std::tuple
>
>};
В строках 1 – 4 код идентичен реализации распределителя в предыдущих случаях (Листинг 75 п. 5.5.1, Листинг 77 п. 5.5.2). Интерес представляет реализация перегруженного оператора (строка 4).
Макросы в строках 5 – 9 предназначены только для облегчения понимания кода, без них конструкция получается запутанной (строка 10).
В строке 5 мы получаем объект вызова, для которого будет проверяться, возвращает ли он значение. Мы запрашиваем нулевой элемент кортежа, поскольку предполагается, что кортеж содержит хотя-бы один объект (иначе зачем распределять вызовы для пустого кортежа?).
В строке 6 определяется тип объекта, который мы запросили. В строке 7 объявляется мета-экземпляр объекта соответствующего типа. Мы говорим «мета-экземпляр», потому что реально объект не создается, но его характеристики используются компилятором для анализа. Конструкция declval необходима, чтобы не было ошибки в случае, если объект не имеет конструктора по умолчанию.
В строке 8 производится мета-вызов с передачей параметров. Мета-вызов здесь имеет тот же смысл, что и мета-экземпляр, т. е. в реальности вызов не производится, а используется для анализа. В строке 9 определяется тип значения, возвращаемого мета-вызовом.
В строке 11 проверяется, является ли тип возвращаемого значения void, и в этом случае вызывается распределяющая функция без возврата результатов (строка 12). В противном случае вызывается распределяющая функция, возвращающая результаты (строка 13).
Использование распределителя с условной компиляцией приведено в Листинг 80.
>struct FOReturn
>{
> int operator() (int eventID) {return 10;}
>};
>struct FOVoid
>{
> void operator() (int eventID) { /*do something*/ }
>};
>struct SResult
>{
> unsigned int code;
> const char* description;