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 // 18 // [func.require] 19 // Define INVOKE (f, t1, t2, ..., tN) as follows: 20 // 1. (t1.*f)(t2, ..., tN) when f is a pointer to a member function of a class T 21 // and t1 is an object of type T or a reference to an object of type T or a 22 // reference to an object of a type derived from T; 23 // 2. ((*t1).*f)(t2, ..., tN) when f is a pointer to a member function of a 24 // class T and t1 is not one of the types described in the previous item; 25 // 3. t1.*f when N == 1 and f is a pointer to member data of a class T and t1 is 26 // an object of type T or a reference to an object of type T or a reference 27 // to an object of a type derived from T; 28 // 4. (*t1).*f when N == 1 and f is a pointer to member data of a class T and t1 29 // is not one of the types described in the previous item; 30 // 5. f(t1, t2, ..., tN) in all other cases. 31 // 32 // The implementation is SFINAE-friendly: substitution failure within invoke() 33 // isn't an error. 34 35 #ifndef ABSL_BASE_INTERNAL_INVOKE_H_ 36 #define ABSL_BASE_INTERNAL_INVOKE_H_ 37 38 #include <algorithm> 39 #include <type_traits> 40 #include <utility> 41 42 #include "absl/meta/type_traits.h" 43 44 // The following code is internal implementation detail. See the comment at the 45 // top of this file for the API documentation. 46 47 namespace absl { 48 ABSL_NAMESPACE_BEGIN 49 namespace base_internal { 50 51 // The five classes below each implement one of the clauses from the definition 52 // of INVOKE. The inner class template Accept<F, Args...> checks whether the 53 // clause is applicable; static function template Invoke(f, args...) does the 54 // invocation. 55 // 56 // By separating the clause selection logic from invocation we make sure that 57 // Invoke() does exactly what the standard says. 58 59 template <typename Derived> 60 struct StrippedAccept { 61 template <typename... Args> 62 struct Accept : Derived::template AcceptImpl<typename std::remove_cv< 63 typename std::remove_reference<Args>::type>::type...> {}; 64 }; 65 66 // (t1.*f)(t2, ..., tN) when f is a pointer to a member function of a class T 67 // and t1 is an object of type T or a reference to an object of type T or a 68 // reference to an object of a type derived from T. 69 struct MemFunAndRef : StrippedAccept<MemFunAndRef> { 70 template <typename... Args> 71 struct AcceptImpl : std::false_type {}; 72 73 template <typename MemFunType, typename C, typename Obj, typename... Args> 74 struct AcceptImpl<MemFunType C::*, Obj, Args...> 75 : std::integral_constant<bool, std::is_base_of<C, Obj>::value && 76 absl::is_function<MemFunType>::value> { 77 }; 78 79 template <typename MemFun, typename Obj, typename... Args> 80 static decltype((std::declval<Obj>().* 81 std::declval<MemFun>())(std::declval<Args>()...)) 82 Invoke(MemFun&& mem_fun, Obj&& obj, Args&&... args) { 83 return (std::forward<Obj>(obj).* 84 std::forward<MemFun>(mem_fun))(std::forward<Args>(args)...); 85 } 86 }; 87 88 // ((*t1).*f)(t2, ..., tN) when f is a pointer to a member function of a 89 // class T and t1 is not one of the types described in the previous item. 90 struct MemFunAndPtr : StrippedAccept<MemFunAndPtr> { 91 template <typename... Args> 92 struct AcceptImpl : std::false_type {}; 93 94 template <typename MemFunType, typename C, typename Ptr, typename... Args> 95 struct AcceptImpl<MemFunType C::*, Ptr, Args...> 96 : std::integral_constant<bool, !std::is_base_of<C, Ptr>::value && 97 absl::is_function<MemFunType>::value> { 98 }; 99 100 template <typename MemFun, typename Ptr, typename... Args> 101 static decltype(((*std::declval<Ptr>()).* 102 std::declval<MemFun>())(std::declval<Args>()...)) 103 Invoke(MemFun&& mem_fun, Ptr&& ptr, Args&&... args) { 104 return ((*std::forward<Ptr>(ptr)).* 105 std::forward<MemFun>(mem_fun))(std::forward<Args>(args)...); 106 } 107 }; 108 109 // t1.*f when N == 1 and f is a pointer to member data of a class T and t1 is 110 // an object of type T or a reference to an object of type T or a reference 111 // to an object of a type derived from T. 112 struct DataMemAndRef : StrippedAccept<DataMemAndRef> { 113 template <typename... Args> 114 struct AcceptImpl : std::false_type {}; 115 116 template <typename R, typename C, typename Obj> 117 struct AcceptImpl<R C::*, Obj> 118 : std::integral_constant<bool, std::is_base_of<C, Obj>::value && 119 !absl::is_function<R>::value> {}; 120 121 template <typename DataMem, typename Ref> 122 static decltype(std::declval<Ref>().*std::declval<DataMem>()) Invoke( 123 DataMem&& data_mem, Ref&& ref) { 124 return std::forward<Ref>(ref).*std::forward<DataMem>(data_mem); 125 } 126 }; 127 128 // (*t1).*f when N == 1 and f is a pointer to member data of a class T and t1 129 // is not one of the types described in the previous item. 130 struct DataMemAndPtr : StrippedAccept<DataMemAndPtr> { 131 template <typename... Args> 132 struct AcceptImpl : std::false_type {}; 133 134 template <typename R, typename C, typename Ptr> 135 struct AcceptImpl<R C::*, Ptr> 136 : std::integral_constant<bool, !std::is_base_of<C, Ptr>::value && 137 !absl::is_function<R>::value> {}; 138 139 template <typename DataMem, typename Ptr> 140 static decltype((*std::declval<Ptr>()).*std::declval<DataMem>()) Invoke( 141 DataMem&& data_mem, Ptr&& ptr) { 142 return (*std::forward<Ptr>(ptr)).*std::forward<DataMem>(data_mem); 143 } 144 }; 145 146 // f(t1, t2, ..., tN) in all other cases. 147 struct Callable { 148 // Callable doesn't have Accept because it's the last clause that gets picked 149 // when none of the previous clauses are applicable. 150 template <typename F, typename... Args> 151 static decltype(std::declval<F>()(std::declval<Args>()...)) Invoke( 152 F&& f, Args&&... args) { 153 return std::forward<F>(f)(std::forward<Args>(args)...); 154 } 155 }; 156 157 // Resolves to the first matching clause. 158 template <typename... Args> 159 struct Invoker { 160 typedef typename std::conditional< 161 MemFunAndRef::Accept<Args...>::value, MemFunAndRef, 162 typename std::conditional< 163 MemFunAndPtr::Accept<Args...>::value, MemFunAndPtr, 164 typename std::conditional< 165 DataMemAndRef::Accept<Args...>::value, DataMemAndRef, 166 typename std::conditional<DataMemAndPtr::Accept<Args...>::value, 167 DataMemAndPtr, Callable>::type>::type>:: 168 type>::type type; 169 }; 170 171 // The result type of Invoke<F, Args...>. 172 template <typename F, typename... Args> 173 using invoke_result_t = decltype(Invoker<F, Args...>::type::Invoke( 174 std::declval<F>(), std::declval<Args>()...)); 175 176 // Invoke(f, args...) is an implementation of INVOKE(f, args...) from section 177 // [func.require] of the C++ standard. 178 template <typename F, typename... Args> 179 invoke_result_t<F, Args...> invoke(F&& f, Args&&... args) { 180 return Invoker<F, Args...>::type::Invoke(std::forward<F>(f), 181 std::forward<Args>(args)...); 182 } 183 } // namespace base_internal 184 ABSL_NAMESPACE_END 185 } // namespace absl 186 187 #endif // ABSL_BASE_INTERNAL_INVOKE_H_ 188