Не могу до конца сообразить как работает данная конструкция в примере использования библиотеки TDLib. сам пример. Итак, в начале создаются вот такие шаблонные классы и функция для возможности передачи нескольких функций обработчику.
namespace detail {
template <class... Fs>
struct overload;
template <class F>
struct overload<F> : public F {
explicit overload(F f) : F(f) {
}
};
template <class F, class... Fs>
struct overload<F, Fs...>
: public overload<F>
, overload<Fs...> {
overload(F f, Fs... fs) : overload<F>(f), overload<Fs...>(fs...) {
}
using overload<F>::operator();
using overload<Fs...>::operator();
};
} // namespace detail
template <class... F>
auto overloaded(F... f) {
return detail::overload<F...>(f...);
}
А потом вызывается сам обработчик для некоего объекта:
td_api::downcast_call(
*update, overloaded(
[this](td_api::updateAuthorizationState &update_authorization_state) {
authorization_state_ = std::move(update_authorization_state.authorization_state_);
on_authorization_state_update();
},
[this](td_api::updateNewChat &update_new_chat) {
chat_title_[update_new_chat.chat_->id_] = update_new_chat.chat_->title_;
},
[this](td_api::updateChatTitle &update_chat_title) {
chat_title_[update_chat_title.chat_id_] = update_chat_title.title_;
},
[this](td_api::updateUser &update_user) {
auto user_id = update_user.user_->id_;
users_[user_id] = std::move(update_user.user_);
},
[this](td_api::updateNewMessage &update_new_message) {
auto chat_id = update_new_message.message_->chat_id_;
auto sender_user_name = get_user_name(update_new_message.message_->sender_user_id_);
std::string text;
if (update_new_message.message_->content_->get_id() == td_api::messageText::ID) {
text = static_cast<td_api::messageText &>(*update_new_message.message_->content_).text_->text_;
}
std::cerr << "Got message: [chat_id:" << chat_id << "] [from:" << sender_user_name << "] ["
<< text << "]" << std::endl;
},
[](auto &update) {}));
сама td_api::downcast_call
простая, она выясняет тип объекта, и передает его в func
.
bool downcast_call(AuthorizationState &obj, const T &func) {
switch (obj.get_id()) {
case authorizationStateWaitTdlibParameters::ID:
func(static_cast<authorizationStateWaitTdlibParameters &>(obj));
return true;
case authorizationStateWaitEncryptionKey::ID:
func(static_cast<authorizationStateWaitEncryptionKey &>(obj));
return true;
мне не очень понятно, как работает функция overloaded
и как выясняется какую именно лямбду вызывать в td_api::downcast_call
. overloaded
, видимо, создает в итоге вложенную друг в друга кучу объектов struct overload<F, Fs...>, struct overload<F>
и так как мы указали, что используем operator()
базового класса, то при вызове func
компилятор находит подходящий operator()
для вызова. Если не так, то поправьте меня пожалуйста. И вообще, есть ли название у такого подхода? Можно ли где-то найти его описание?
Специализация класса overload
со множеством параметров наследует от пачки специализаций класса overload
с одним параметром. Каждый из этих базовых классов наследует от анонимного класса, созданного лямбда-выражением и имеет оператор ()
с сигнатурой как у того лямбда-выражения. Затем все перегруженные операторы ()
из базовых классов переносятся в наследующий класс посредством директив using overload<F>::operator(); using overload<Fs...>::operator();
. Этот шаг принципиально важен, так как компилятор может выбирать из перегруженных функций, относящихся только к одному классу.
Таким образом, в результате получается специализация класса overload
c набором перегрузок, соответствующим сигнатурам переданных лямбд.
Кофе для программистов: как напиток влияет на продуктивность кодеров?
Рекламные вывески: как привлечь внимание и увеличить продажи
Стратегії та тренди в SMM - Технології, що формують майбутнє сьогодні
Выделенный сервер, что это, для чего нужен и какие характеристики важны?
Современные решения для бизнеса: как облачные и виртуальные технологии меняют рынок
У меня есть задача: сложить все элементы массива заранее не зная сколько их и потом эту сумму сделать значением переменнойПомогите пожалуйста!
Заранее извеняюсь, если вопрос вам заставит долго читать, но так как вопросов не очень много, решил позволить себя
Например у меня есть функция int foo() {return 0;};И где нибудь в main я буду вызывать foo() , а как оператор () работает в данном случае ?