Обратные вызовы в C++ | страница 66
>template
>void Call(CallData& data) // (1)
>{
>}
>template
>void Call(CallData& data, First& first, Others&…rest) // (2)
>{
> std::apply(first, data); // (3)
> Call(data, rest…); // (4)
>}
>template
>void Distribute1(std::tuple
>{
> Call(data, objects…); // (6)
>}
Распределяющая функция объявлена в строке 5. Входными параметрами функции являются кортеж данных вызова data и пакет объектов вызова objects, типы их содержимого задаются параметрами шаблона. Внутри этой функции, в строке 6, происходит первый вызов рекурсивной функции, которой передаются соответствующие аргументы – кортеж и пакет.
Рекурсивная функция объявлена в строке 2. Эта функция извлекает очередной объект из пакета и осуществляет его вызов (строка 3). Здесь используется функция стандартной библиотеки std::apply, которая преобразует содержимое кортежа в список аргументов. Далее, в строке 4, пакет с оставшимися параметрами передается в рекурсивный вызов Call, и процесс повторяется до завершения рекурсии.
5.3.3. Способ 2: объекты в кортеж, данные в пакет
При использовании данного способа необходимо пройти по всем элементам кортежа и осуществить вызовы хранимых в нем объектов, передавая на вход пакет данных. Как осуществить обход содержимого кортежа?
Доступ к элементам кортежа осуществляется с помощью вызова
std::get
где index – это порядковый номер элемента (начиная с 0), tuple – имя переменной-кортежа. Проблема в том, что индексы должны быть заранее определены как числовые константы, использование переменной для задания индекса не допускается31. Поэтому здесь нельзя использовать ни циклы, ни функции с входным аргументом – индексом.
Можно попробовать объявить шаблон функции, в которой индекс задается параметром шаблона, а внутри функции изменить индекс и осуществить рекурсивный вызов. По идее, в этом случае для каждого индекса должна была бы сгенерироваться отдельная специализированная функция, однако стандарт не допускает специализацию шаблонов функций32. Но специализация шаблонов классов допустима, поэтому выходом будет обернуть функцию в класс – оболочку и уже для класса объявлять специализацию по индексам. Реализация приведена в Листинг 69.
>template