1 // Copyright 2017 The Abseil Authors. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // https://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 // 15 // absl::base_internal::invoke(f, args...) is an implementation of 16 // INVOKE(f, args...) from section [func.require] of the C++ standard. 17 // When compiled as C++17 and later versions, it is implemented as an alias of 18 // std::invoke. 19 // 20 // [func.require] 21 // Define INVOKE (f, t1, t2, ..., tN) as follows: 22 // 1. (t1.*f)(t2, ..., tN) when f is a pointer to a member function of a class T 23 // and t1 is an object of type T or a reference to an object of type T or a 24 // reference to an object of a type derived from T; 25 // 2. ((*t1).*f)(t2, ..., tN) when f is a pointer to a member function of a 26 // class T and t1 is not one of the types described in the previous item; 27 // 3. t1.*f when N == 1 and f is a pointer to member data of a class T and t1 is 28 // an object of type T or a reference to an object of type T or a reference 29 // to an object of a type derived from T; 30 // 4. (*t1).*f when N == 1 and f is a pointer to member data of a class T and t1 31 // is not one of the types described in the previous item; 32 // 5. f(t1, t2, ..., tN) in all other cases. 33 // 34 // The implementation is SFINAE-friendly: substitution failure within invoke() 35 // isn't an error. 36 37 #ifndef ABSL_BASE_INTERNAL_INVOKE_H_ 38 #define ABSL_BASE_INTERNAL_INVOKE_H_ 39 40 #include "absl/base/config.h" 41 42 #if ABSL_INTERNAL_CPLUSPLUS_LANG >= 201703L 43 44 #include <functional> 45 46 namespace absl { 47 ABSL_NAMESPACE_BEGIN 48 namespace base_internal { 49 50 using std::invoke; 51 using std::invoke_result_t; 52 using std::is_invocable_r; 53 54 } // namespace base_internal 55 ABSL_NAMESPACE_END 56 } // namespace absl 57 58 #else // ABSL_INTERNAL_CPLUSPLUS_LANG >= 201703L 59 60 #include <algorithm> 61 #include <type_traits> 62 #include <utility> 63 64 #include "absl/meta/type_traits.h" 65 66 // The following code is internal implementation detail. See the comment at the 67 // top of this file for the API documentation. 68 69 namespace absl { 70 ABSL_NAMESPACE_BEGIN 71 namespace base_internal { 72 73 // The five classes below each implement one of the clauses from the definition 74 // of INVOKE. The inner class template Accept<F, Args...> checks whether the 75 // clause is applicable; static function template Invoke(f, args...) does the 76 // invocation. 77 // 78 // By separating the clause selection logic from invocation we make sure that 79 // Invoke() does exactly what the standard says. 80 81 template <typename Derived> 82 struct StrippedAccept { 83 template <typename... Args> 84 struct Accept : Derived::template AcceptImpl<typename std::remove_cv< 85 typename std::remove_reference<Args>::type>::type...> {}; 86 }; 87 88 // (t1.*f)(t2, ..., tN) when f is a pointer to a member function of a class T 89 // and t1 is an object of type T or a reference to an object of type T or a 90 // reference to an object of a type derived from T. 91 struct MemFunAndRef : StrippedAccept<MemFunAndRef> { 92 template <typename... Args> 93 struct AcceptImpl : std::false_type {}; 94 95 template <typename MemFunType, typename C, typename Obj, typename... Args> 96 struct AcceptImpl<MemFunType C::*, Obj, Args...> 97 : std::integral_constant<bool, std::is_base_of<C, Obj>::value && 98 absl::is_function<MemFunType>::value> { 99 }; 100 101 template <typename MemFun, typename Obj, typename... Args> 102 static decltype((std::declval<Obj>().* 103 std::declval<MemFun>())(std::declval<Args>()...)) 104 Invoke(MemFun&& mem_fun, Obj&& obj, Args&&... args) { 105 // Ignore bogus GCC warnings on this line. 106 // See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=101436 for similar example. 107 #if ABSL_INTERNAL_HAVE_MIN_GNUC_VERSION(11, 0) 108 #pragma GCC diagnostic push 109 #pragma GCC diagnostic ignored "-Warray-bounds" 110 #pragma GCC diagnostic ignored "-Wmaybe-uninitialized" 111 #endif 112 return (std::forward<Obj>(obj).* 113 std::forward<MemFun>(mem_fun))(std::forward<Args>(args)...); 114 #if ABSL_INTERNAL_HAVE_MIN_GNUC_VERSION(11, 0) 115 #pragma GCC diagnostic pop 116 #endif 117 } 118 }; 119 120 // ((*t1).*f)(t2, ..., tN) when f is a pointer to a member function of a 121 // class T and t1 is not one of the types described in the previous item. 122 struct MemFunAndPtr : StrippedAccept<MemFunAndPtr> { 123 template <typename... Args> 124 struct AcceptImpl : std::false_type {}; 125 126 template <typename MemFunType, typename C, typename Ptr, typename... Args> 127 struct AcceptImpl<MemFunType C::*, Ptr, Args...> 128 : std::integral_constant<bool, !std::is_base_of<C, Ptr>::value && 129 absl::is_function<MemFunType>::value> { 130 }; 131 132 template <typename MemFun, typename Ptr, typename... Args> 133 static decltype(((*std::declval<Ptr>()).* 134 std::declval<MemFun>())(std::declval<Args>()...)) 135 Invoke(MemFun&& mem_fun, Ptr&& ptr, Args&&... args) { 136 return ((*std::forward<Ptr>(ptr)).* 137 std::forward<MemFun>(mem_fun))(std::forward<Args>(args)...); 138 } 139 }; 140 141 // t1.*f when N == 1 and f is a pointer to member data of a class T and t1 is 142 // an object of type T or a reference to an object of type T or a reference 143 // to an object of a type derived from T. 144 struct DataMemAndRef : StrippedAccept<DataMemAndRef> { 145 template <typename... Args> 146 struct AcceptImpl : std::false_type {}; 147 148 template <typename R, typename C, typename Obj> 149 struct AcceptImpl<R C::*, Obj> 150 : std::integral_constant<bool, std::is_base_of<C, Obj>::value && 151 !absl::is_function<R>::value> {}; 152 153 template <typename DataMem, typename Ref> 154 static decltype(std::declval<Ref>().*std::declval<DataMem>()) Invoke( 155 DataMem&& data_mem, Ref&& ref) { 156 return std::forward<Ref>(ref).*std::forward<DataMem>(data_mem); 157 } 158 }; 159 160 // (*t1).*f when N == 1 and f is a pointer to member data of a class T and t1 161 // is not one of the types described in the previous item. 162 struct DataMemAndPtr : StrippedAccept<DataMemAndPtr> { 163 template <typename... Args> 164 struct AcceptImpl : std::false_type {}; 165 166 template <typename R, typename C, typename Ptr> 167 struct AcceptImpl<R C::*, Ptr> 168 : std::integral_constant<bool, !std::is_base_of<C, Ptr>::value && 169 !absl::is_function<R>::value> {}; 170 171 template <typename DataMem, typename Ptr> 172 static decltype((*std::declval<Ptr>()).*std::declval<DataMem>()) Invoke( 173 DataMem&& data_mem, Ptr&& ptr) { 174 return (*std::forward<Ptr>(ptr)).*std::forward<DataMem>(data_mem); 175 } 176 }; 177 178 // f(t1, t2, ..., tN) in all other cases. 179 struct Callable { 180 // Callable doesn't have Accept because it's the last clause that gets picked 181 // when none of the previous clauses are applicable. 182 template <typename F, typename... Args> 183 static decltype(std::declval<F>()(std::declval<Args>()...)) Invoke( 184 F&& f, Args&&... args) { 185 return std::forward<F>(f)(std::forward<Args>(args)...); 186 } 187 }; 188 189 // Resolves to the first matching clause. 190 template <typename... Args> 191 struct Invoker { 192 typedef typename std::conditional< 193 MemFunAndRef::Accept<Args...>::value, MemFunAndRef, 194 typename std::conditional< 195 MemFunAndPtr::Accept<Args...>::value, MemFunAndPtr, 196 typename std::conditional< 197 DataMemAndRef::Accept<Args...>::value, DataMemAndRef, 198 typename std::conditional<DataMemAndPtr::Accept<Args...>::value, 199 DataMemAndPtr, Callable>::type>::type>:: 200 type>::type type; 201 }; 202 203 // The result type of Invoke<F, Args...>. 204 template <typename F, typename... Args> 205 using invoke_result_t = decltype(Invoker<F, Args...>::type::Invoke( 206 std::declval<F>(), std::declval<Args>()...)); 207 208 // Invoke(f, args...) is an implementation of INVOKE(f, args...) from section 209 // [func.require] of the C++ standard. 210 template <typename F, typename... Args> 211 invoke_result_t<F, Args...> invoke(F&& f, Args&&... args) { 212 return Invoker<F, Args...>::type::Invoke(std::forward<F>(f), 213 std::forward<Args>(args)...); 214 } 215 216 template <typename AlwaysVoid, typename, typename, typename...> 217 struct IsInvocableRImpl : std::false_type {}; 218 219 template <typename R, typename F, typename... Args> 220 struct IsInvocableRImpl< 221 absl::void_t<absl::base_internal::invoke_result_t<F, Args...> >, R, F, 222 Args...> 223 : std::integral_constant< 224 bool, 225 std::is_convertible<absl::base_internal::invoke_result_t<F, Args...>, 226 R>::value || 227 std::is_void<R>::value> {}; 228 229 // Type trait whose member `value` is true if invoking `F` with `Args` is valid, 230 // and either the return type is convertible to `R`, or `R` is void. 231 // C++11-compatible version of `std::is_invocable_r`. 232 template <typename R, typename F, typename... Args> 233 using is_invocable_r = IsInvocableRImpl<void, R, F, Args...>; 234 235 } // namespace base_internal 236 ABSL_NAMESPACE_END 237 } // namespace absl 238 239 #endif // ABSL_INTERNAL_CPLUSPLUS_LANG >= 201703L 240 241 #endif // ABSL_BASE_INTERNAL_INVOKE_H_ 242