// // Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2024 // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // #pragma once #include "td/utils/common.h" #include #include #include #include namespace td { namespace detail { template struct IntSeq {}; template struct IntSeqGen : IntSeqGen {}; template struct IntSeqGen { using type = IntSeq; }; template class LogicAndImpl {}; template class LogicAndImpl { public: static constexpr bool value = LogicAndImpl<(Res && X), Args...>::value; }; template class LogicAndImpl { public: static constexpr bool value = Res; }; template using IntRange = typename IntSeqGen<0, N>::type; template struct is_reference_wrapper : std::false_type {}; template struct is_reference_wrapper> : std::true_type {}; template auto invoke_impl(T Base::*pmf, Derived &&ref, Args &&...args) noexcept(noexcept((std::forward(ref).*pmf)(std::forward(args)...))) -> std::enable_if_t::value && std::is_base_of>::value, decltype((std::forward(ref).*pmf)(std::forward(args)...))> { return (std::forward(ref).*pmf)(std::forward(args)...); } template auto invoke_impl(T Base::*pmf, RefWrap &&ref, Args &&...args) noexcept(noexcept((ref.get().*pmf)(std::forward(args)...))) -> std::enable_if_t::value && is_reference_wrapper>::value, decltype((ref.get().*pmf)(std::forward(args)...))> { return (ref.get().*pmf)(std::forward(args)...); } template auto invoke_impl(T Base::*pmf, Pointer &&ptr, Args &&...args) noexcept(noexcept(((*std::forward(ptr)).*pmf)(std::forward(args)...))) -> std::enable_if_t::value && !is_reference_wrapper>::value && !std::is_base_of>::value, decltype(((*std::forward(ptr)).*pmf)(std::forward(args)...))> { return ((*std::forward(ptr)).*pmf)(std::forward(args)...); } template auto invoke_impl(T Base::*pmd, Derived &&ref) noexcept(noexcept(std::forward(ref).*pmd)) -> std::enable_if_t::value && std::is_base_of>::value, decltype(std::forward(ref).*pmd)> { return std::forward(ref).*pmd; } template auto invoke_impl(T Base::*pmd, RefWrap &&ref) noexcept(noexcept(ref.get().*pmd)) -> std::enable_if_t::value && is_reference_wrapper>::value, decltype(ref.get().*pmd)> { return ref.get().*pmd; } template auto invoke_impl(T Base::*pmd, Pointer &&ptr) noexcept(noexcept((*std::forward(ptr)).*pmd)) -> std::enable_if_t::value && !is_reference_wrapper>::value && !std::is_base_of>::value, decltype((*std::forward(ptr)).*pmd)> { return (*std::forward(ptr)).*pmd; } template auto invoke_impl(F &&f, Args &&...args) noexcept(noexcept(std::forward(f)(std::forward(args)...))) -> std::enable_if_t>::value, decltype(std::forward(f)(std::forward(args)...))> { return std::forward(f)(std::forward(args)...); } template auto invoke(F &&f, ArgTypes &&...args) noexcept(noexcept(invoke_impl(std::forward(f), std::forward(args)...))) -> decltype(invoke_impl(std::forward(f), std::forward(args)...)) { return invoke_impl(std::forward(f), std::forward(args)...); } template auto call_tuple_impl(F &&func, std::tuple &&tuple, IntSeq) { return func(std::forward(std::get(tuple))...); } template auto invoke_tuple_impl(std::tuple &&tuple, IntSeq) { return invoke(std::forward(std::get(tuple))...); } template auto mem_call_tuple_impl(ActorT *actor, std::tuple &&tuple, IntSeq<0, S...>) { return (actor->*std::get<0>(tuple))(std::forward(std::get(tuple))...); } template void tuple_for_each_impl(std::tuple &tuple, const F &func, IntSeq) { const auto &dummy = {0, (func(std::get(tuple)), 0)...}; (void)dummy; } template void tuple_for_each_impl(const std::tuple &tuple, const F &func, IntSeq) { const auto &dummy = {0, (func(std::get(tuple)), 0)...}; (void)dummy; } } // namespace detail template class LogicAnd { public: static constexpr bool value = detail::LogicAndImpl::value; }; template auto call_tuple(F &&func, std::tuple &&tuple) { return detail::call_tuple_impl(func, std::move(tuple), detail::IntRange()); } template auto invoke_tuple(std::tuple &&tuple) { return detail::invoke_tuple_impl(std::move(tuple), detail::IntRange()); } template auto mem_call_tuple(ActorT *actor, std::tuple &&tuple) { return detail::mem_call_tuple_impl(actor, std::move(tuple), detail::IntRange()); } template void tuple_for_each(std::tuple &tuple, const F &func) { detail::tuple_for_each_impl(tuple, func, detail::IntRange()); } template void tuple_for_each(const std::tuple &tuple, const F &func) { detail::tuple_for_each_impl(tuple, func, detail::IntRange()); } template = 0> auto &&get_nth_argument(Arg &&arg, Args &&...args) { return std::forward(arg); } template = 0> auto &&get_nth_argument(Arg &&arg, Args &&...args) { return get_nth_argument(std::forward(args)...); } template auto &&get_last_argument(Args &&...args) { return get_nth_argument(std::forward(args)...); } namespace detail { template auto call_n_arguments_impl(IntSeq, F &&f, Args &&...args) { return f(get_nth_argument(std::forward(args)...)...); } } // namespace detail template auto call_n_arguments(F &&f, Args &&...args) { return detail::call_n_arguments_impl(detail::IntRange(), f, std::forward(args)...); } template struct is_callable final : public std::false_type {}; template struct is_callable()(std::declval()))> final : public std::true_type {}; } // namespace td