1 // 2 // Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2021 3 // 4 // Distributed under the Boost Software License, Version 1.0. (See accompanying 5 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 6 // 7 #pragma once 8 9 #include "td/utils/common.h" 10 11 #include <functional> 12 #include <tuple> 13 #include <type_traits> 14 #include <utility> 15 16 namespace td { 17 18 namespace detail { 19 20 template <std::size_t... S> 21 struct IntSeq {}; 22 23 template <std::size_t L, std::size_t N, std::size_t... S> 24 struct IntSeqGen : IntSeqGen<L, N - 1, L + N - 1, S...> {}; 25 26 template <std::size_t L, std::size_t... S> 27 struct IntSeqGen<L, 0, S...> { 28 using type = IntSeq<S...>; 29 }; 30 31 template <bool... Args> 32 class LogicAndImpl {}; 33 34 template <bool Res, bool X, bool... Args> 35 class LogicAndImpl<Res, X, Args...> { 36 public: 37 static constexpr bool value = LogicAndImpl<(Res && X), Args...>::value; 38 }; 39 40 template <bool Res> 41 class LogicAndImpl<Res> { 42 public: 43 static constexpr bool value = Res; 44 }; 45 46 template <std::size_t N> 47 using IntRange = typename IntSeqGen<0, N>::type; 48 49 template <class T> 50 struct is_reference_wrapper : std::false_type {}; 51 52 template <class U> 53 struct is_reference_wrapper<std::reference_wrapper<U>> : std::true_type {}; 54 55 template <class Base, class T, class Derived, class... Args> 56 auto invoke_impl(T Base::*pmf, Derived &&ref, 57 Args &&... args) noexcept(noexcept((std::forward<Derived>(ref).*pmf)(std::forward<Args>(args)...))) 58 -> std::enable_if_t<std::is_function<T>::value && std::is_base_of<Base, std::decay<Derived>>::value, 59 decltype((std::forward<Derived>(ref).*pmf)(std::forward<Args>(args)...))> { 60 return (std::forward<Derived>(ref).*pmf)(std::forward<Args>(args)...); 61 } 62 63 template <class Base, class T, class RefWrap, class... Args> 64 auto invoke_impl(T Base::*pmf, RefWrap &&ref, 65 Args &&... args) noexcept(noexcept((ref.get().*pmf)(std::forward<Args>(args)...))) 66 -> std::enable_if_t<std::is_function<T>::value && is_reference_wrapper<std::decay_t<RefWrap>>::value, 67 decltype((ref.get().*pmf)(std::forward<Args>(args)...))> 68 69 { 70 return (ref.get().*pmf)(std::forward<Args>(args)...); 71 } 72 73 template <class Base, class T, class Pointer, class... Args> 74 auto invoke_impl(T Base::*pmf, Pointer &&ptr, 75 Args &&... args) noexcept(noexcept(((*std::forward<Pointer>(ptr)).*pmf)(std::forward<Args>(args)...))) 76 -> std::enable_if_t<std::is_function<T>::value && !is_reference_wrapper<std::decay_t<Pointer>>::value && 77 !std::is_base_of<Base, std::decay_t<Pointer>>::value, 78 decltype(((*std::forward<Pointer>(ptr)).*pmf)(std::forward<Args>(args)...))> { 79 return ((*std::forward<Pointer>(ptr)).*pmf)(std::forward<Args>(args)...); 80 } 81 82 template <class Base, class T, class Derived> 83 auto invoke_impl(T Base::*pmd, Derived &&ref) noexcept(noexcept(std::forward<Derived>(ref).*pmd)) 84 -> std::enable_if_t<!std::is_function<T>::value && std::is_base_of<Base, std::decay_t<Derived>>::value, 85 decltype(std::forward<Derived>(ref).*pmd)> { 86 return std::forward<Derived>(ref).*pmd; 87 } 88 89 template <class Base, class T, class RefWrap> 90 auto invoke_impl(T Base::*pmd, RefWrap &&ref) noexcept(noexcept(ref.get().*pmd)) 91 -> std::enable_if_t<!std::is_function<T>::value && is_reference_wrapper<std::decay_t<RefWrap>>::value, 92 decltype(ref.get().*pmd)> { 93 return ref.get().*pmd; 94 } 95 96 template <class Base, class T, class Pointer> 97 auto invoke_impl(T Base::*pmd, Pointer &&ptr) noexcept(noexcept((*std::forward<Pointer>(ptr)).*pmd)) 98 -> std::enable_if_t<!std::is_function<T>::value && !is_reference_wrapper<std::decay_t<Pointer>>::value && 99 !std::is_base_of<Base, std::decay_t<Pointer>>::value, 100 decltype((*std::forward<Pointer>(ptr)).*pmd)> { 101 return (*std::forward<Pointer>(ptr)).*pmd; 102 } 103 104 template <class F, class... Args> 105 auto invoke_impl(F &&f, Args &&... args) noexcept(noexcept(std::forward<F>(f)(std::forward<Args>(args)...))) 106 -> std::enable_if_t<!std::is_member_pointer<std::decay_t<F>>::value, 107 decltype(std::forward<F>(f)(std::forward<Args>(args)...))> { 108 return std::forward<F>(f)(std::forward<Args>(args)...); 109 } 110 111 template <class F, class... ArgTypes> 112 auto invoke(F &&f, 113 ArgTypes &&... args) noexcept(noexcept(invoke_impl(std::forward<F>(f), std::forward<ArgTypes>(args)...))) 114 -> decltype(invoke_impl(std::forward<F>(f), std::forward<ArgTypes>(args)...)) { 115 return invoke_impl(std::forward<F>(f), std::forward<ArgTypes>(args)...); 116 } 117 118 template <class F, class... Args, std::size_t... S> 119 auto call_tuple_impl(F &&func, std::tuple<Args...> &&tuple, IntSeq<S...>) { 120 return func(std::forward<Args>(std::get<S>(tuple))...); 121 } 122 123 template <class... Args, std::size_t... S> 124 auto invoke_tuple_impl(std::tuple<Args...> &&tuple, IntSeq<S...>) { 125 return invoke(std::forward<Args>(std::get<S>(tuple))...); 126 } 127 128 template <class ActorT, class F, class... Args, std::size_t... S> 129 auto mem_call_tuple_impl(ActorT *actor, std::tuple<F, Args...> &&tuple, IntSeq<0, S...>) { 130 return (actor->*std::get<0>(tuple))(std::forward<Args>(std::get<S>(tuple))...); 131 } 132 133 template <class F, class... Args, std::size_t... S> 134 void tuple_for_each_impl(std::tuple<Args...> &tuple, const F &func, IntSeq<S...>) { 135 const auto &dummy = {0, (func(std::get<S>(tuple)), 0)...}; 136 (void)dummy; 137 } 138 139 template <class F, class... Args, std::size_t... S> 140 void tuple_for_each_impl(const std::tuple<Args...> &tuple, const F &func, IntSeq<S...>) { 141 const auto &dummy = {0, (func(std::get<S>(tuple)), 0)...}; 142 (void)dummy; 143 } 144 145 } // namespace detail 146 147 template <bool... Args> 148 class LogicAnd { 149 public: 150 static constexpr bool value = detail::LogicAndImpl<true, Args...>::value; 151 }; 152 153 template <class F, class... Args> 154 auto call_tuple(F &&func, std::tuple<Args...> &&tuple) { 155 return detail::call_tuple_impl(func, std::move(tuple), detail::IntRange<sizeof...(Args)>()); 156 } 157 158 template <class... Args> 159 auto invoke_tuple(std::tuple<Args...> &&tuple) { 160 return detail::invoke_tuple_impl(std::move(tuple), detail::IntRange<sizeof...(Args)>()); 161 } 162 163 template <class ActorT, class... Args> 164 auto mem_call_tuple(ActorT *actor, std::tuple<Args...> &&tuple) { 165 return detail::mem_call_tuple_impl(actor, std::move(tuple), detail::IntRange<sizeof...(Args)>()); 166 } 167 168 template <class F, class... Args> 169 void tuple_for_each(std::tuple<Args...> &tuple, const F &func) { 170 detail::tuple_for_each_impl(tuple, func, detail::IntRange<sizeof...(Args)>()); 171 } 172 173 template <class F, class... Args> 174 void tuple_for_each(const std::tuple<Args...> &tuple, const F &func) { 175 detail::tuple_for_each_impl(tuple, func, detail::IntRange<sizeof...(Args)>()); 176 } 177 178 template <size_t N, class Arg, class... Args, std::enable_if_t<N == 0, int> = 0> 179 auto &&get_nth_argument(Arg &&arg, Args &&... args) { 180 return std::forward<Arg>(arg); 181 } 182 183 template <size_t N, class Arg, class... Args, std::enable_if_t<N != 0, int> = 0> 184 auto &&get_nth_argument(Arg &&arg, Args &&... args) { 185 return get_nth_argument<N - 1>(std::forward<Args &&>(args)...); 186 } 187 188 template <class... Args> 189 auto &&get_last_argument(Args &&... args) { 190 return get_nth_argument<sizeof...(Args) - 1>(std::forward<Args &&>(args)...); 191 } 192 193 namespace detail { 194 template <class F, class... Args, std::size_t... S> 195 auto call_n_arguments_impl(IntSeq<S...>, F &&f, Args &&... args) { 196 return f(get_nth_argument<S>(std::forward<Args>(args)...)...); 197 } 198 } // namespace detail 199 200 template <size_t N, class F, class... Args> 201 auto call_n_arguments(F &&f, Args &&... args) { 202 return detail::call_n_arguments_impl(detail::IntRange<N>(), f, std::forward<Args>(args)...); 203 } 204 205 template <class F, class X, class = void> 206 struct is_callable final : public std::false_type {}; 207 template <class F, class X> 208 struct is_callable<F, X, decltype(std::declval<F>()(std::declval<X>()))> final : public std::true_type {}; 209 210 } // namespace td 211