You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

invoke.h 10 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267
  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. #ifndef ABSL_BASE_INTERNAL_INVOKE_H_
  37. #define ABSL_BASE_INTERNAL_INVOKE_H_
  38. #include "absl/base/config.h"
  39. #if ABSL_INTERNAL_CPLUSPLUS_LANG >= 201703L
  40. #include <functional>
  41. namespace absl
  42. {
  43. ABSL_NAMESPACE_BEGIN
  44. namespace base_internal
  45. {
  46. using std::invoke;
  47. using std::invoke_result_t;
  48. using std::is_invocable_r;
  49. } // namespace base_internal
  50. ABSL_NAMESPACE_END
  51. } // namespace absl
  52. #else // ABSL_INTERNAL_CPLUSPLUS_LANG >= 201703L
  53. #include <algorithm>
  54. #include <type_traits>
  55. #include <utility>
  56. #include "absl/meta/type_traits.h"
  57. // The following code is internal implementation detail. See the comment at the
  58. // top of this file for the API documentation.
  59. namespace absl
  60. {
  61. ABSL_NAMESPACE_BEGIN
  62. namespace base_internal
  63. {
  64. // The five classes below each implement one of the clauses from the definition
  65. // of INVOKE. The inner class template Accept<F, Args...> checks whether the
  66. // clause is applicable; static function template Invoke(f, args...) does the
  67. // invocation.
  68. //
  69. // By separating the clause selection logic from invocation we make sure that
  70. // Invoke() does exactly what the standard says.
  71. template<typename Derived>
  72. struct StrippedAccept
  73. {
  74. template<typename... Args>
  75. struct Accept : Derived::template AcceptImpl<typename std::remove_cv<typename std::remove_reference<Args>::type>::type...>
  76. {
  77. };
  78. };
  79. // (t1.*f)(t2, ..., tN) when f is a pointer to a member function of a class T
  80. // and t1 is an object of type T or a reference to an object of type T or a
  81. // reference to an object of a type derived from T.
  82. struct MemFunAndRef : StrippedAccept<MemFunAndRef>
  83. {
  84. template<typename... Args>
  85. struct AcceptImpl : std::false_type
  86. {
  87. };
  88. template<typename MemFunType, typename C, typename Obj, typename... Args>
  89. struct AcceptImpl<MemFunType C::*, Obj, Args...> : std::integral_constant<bool, std::is_base_of<C, Obj>::value && absl::is_function<MemFunType>::value>
  90. {
  91. };
  92. template<typename MemFun, typename Obj, typename... Args>
  93. static decltype((std::declval<Obj>().*std::declval<MemFun>())(std::declval<Args>()...))
  94. Invoke(MemFun&& mem_fun, Obj&& obj, Args&&... args)
  95. {
  96. // Ignore bogus GCC warnings on this line.
  97. // See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=101436 for similar example.
  98. #if ABSL_INTERNAL_HAVE_MIN_GNUC_VERSION(11, 0)
  99. #pragma GCC diagnostic push
  100. #pragma GCC diagnostic ignored "-Warray-bounds"
  101. #pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
  102. #endif
  103. return (std::forward<Obj>(obj).*std::forward<MemFun>(mem_fun))(std::forward<Args>(args)...);
  104. #if ABSL_INTERNAL_HAVE_MIN_GNUC_VERSION(11, 0)
  105. #pragma GCC diagnostic pop
  106. #endif
  107. }
  108. };
  109. // ((*t1).*f)(t2, ..., tN) when f is a pointer to a member function of a
  110. // class T and t1 is not one of the types described in the previous item.
  111. struct MemFunAndPtr : StrippedAccept<MemFunAndPtr>
  112. {
  113. template<typename... Args>
  114. struct AcceptImpl : std::false_type
  115. {
  116. };
  117. template<typename MemFunType, typename C, typename Ptr, typename... Args>
  118. struct AcceptImpl<MemFunType C::*, Ptr, Args...> : std::integral_constant<bool, !std::is_base_of<C, Ptr>::value && absl::is_function<MemFunType>::value>
  119. {
  120. };
  121. template<typename MemFun, typename Ptr, typename... Args>
  122. static decltype(((*std::declval<Ptr>()).*std::declval<MemFun>())(std::declval<Args>()...))
  123. Invoke(MemFun&& mem_fun, Ptr&& ptr, Args&&... args)
  124. {
  125. return ((*std::forward<Ptr>(ptr)).*std::forward<MemFun>(mem_fun))(std::forward<Args>(args)...);
  126. }
  127. };
  128. // t1.*f when N == 1 and f is a pointer to member data of a class T and t1 is
  129. // an object of type T or a reference to an object of type T or a reference
  130. // to an object of a type derived from T.
  131. struct DataMemAndRef : StrippedAccept<DataMemAndRef>
  132. {
  133. template<typename... Args>
  134. struct AcceptImpl : std::false_type
  135. {
  136. };
  137. template<typename R, typename C, typename Obj>
  138. struct AcceptImpl<R C::*, Obj> : std::integral_constant<bool, std::is_base_of<C, Obj>::value && !absl::is_function<R>::value>
  139. {
  140. };
  141. template<typename DataMem, typename Ref>
  142. static decltype(std::declval<Ref>().*std::declval<DataMem>()) Invoke(
  143. DataMem&& data_mem, Ref&& ref
  144. )
  145. {
  146. return std::forward<Ref>(ref).*std::forward<DataMem>(data_mem);
  147. }
  148. };
  149. // (*t1).*f when N == 1 and f is a pointer to member data of a class T and t1
  150. // is not one of the types described in the previous item.
  151. struct DataMemAndPtr : StrippedAccept<DataMemAndPtr>
  152. {
  153. template<typename... Args>
  154. struct AcceptImpl : std::false_type
  155. {
  156. };
  157. template<typename R, typename C, typename Ptr>
  158. struct AcceptImpl<R C::*, Ptr> : std::integral_constant<bool, !std::is_base_of<C, Ptr>::value && !absl::is_function<R>::value>
  159. {
  160. };
  161. template<typename DataMem, typename Ptr>
  162. static decltype((*std::declval<Ptr>()).*std::declval<DataMem>()) Invoke(
  163. DataMem&& data_mem, Ptr&& ptr
  164. )
  165. {
  166. return (*std::forward<Ptr>(ptr)).*std::forward<DataMem>(data_mem);
  167. }
  168. };
  169. // f(t1, t2, ..., tN) in all other cases.
  170. struct Callable
  171. {
  172. // Callable doesn't have Accept because it's the last clause that gets picked
  173. // when none of the previous clauses are applicable.
  174. template<typename F, typename... Args>
  175. static decltype(std::declval<F>()(std::declval<Args>()...)) Invoke(
  176. F&& f, Args&&... args
  177. )
  178. {
  179. return std::forward<F>(f)(std::forward<Args>(args)...);
  180. }
  181. };
  182. // Resolves to the first matching clause.
  183. template<typename... Args>
  184. struct Invoker
  185. {
  186. typedef typename std::conditional<
  187. MemFunAndRef::Accept<Args...>::value,
  188. MemFunAndRef,
  189. typename std::conditional<
  190. MemFunAndPtr::Accept<Args...>::value,
  191. MemFunAndPtr,
  192. typename std::conditional<
  193. DataMemAndRef::Accept<Args...>::value,
  194. DataMemAndRef,
  195. typename std::conditional<DataMemAndPtr::Accept<Args...>::value, DataMemAndPtr, Callable>::type>::type>::
  196. type>::type type;
  197. };
  198. // The result type of Invoke<F, Args...>.
  199. template<typename F, typename... Args>
  200. using invoke_result_t = decltype(Invoker<F, Args...>::type::Invoke(
  201. std::declval<F>(), std::declval<Args>()...
  202. ));
  203. // Invoke(f, args...) is an implementation of INVOKE(f, args...) from section
  204. // [func.require] of the C++ standard.
  205. template<typename F, typename... Args>
  206. invoke_result_t<F, Args...> invoke(F&& f, Args&&... args)
  207. {
  208. return Invoker<F, Args...>::type::Invoke(std::forward<F>(f), std::forward<Args>(args)...);
  209. }
  210. template<typename AlwaysVoid, typename, typename, typename...>
  211. struct IsInvocableRImpl : std::false_type
  212. {
  213. };
  214. template<typename R, typename F, typename... Args>
  215. struct IsInvocableRImpl<
  216. absl::void_t<absl::base_internal::invoke_result_t<F, Args...>>,
  217. R,
  218. F,
  219. Args...> : std::integral_constant<bool, std::is_convertible<absl::base_internal::invoke_result_t<F, Args...>, R>::value || std::is_void<R>::value>
  220. {
  221. };
  222. // Type trait whose member `value` is true if invoking `F` with `Args` is valid,
  223. // and either the return type is convertible to `R`, or `R` is void.
  224. // C++11-compatible version of `std::is_invocable_r`.
  225. template<typename R, typename F, typename... Args>
  226. using is_invocable_r = IsInvocableRImpl<void, R, F, Args...>;
  227. } // namespace base_internal
  228. ABSL_NAMESPACE_END
  229. } // namespace absl
  230. #endif // ABSL_INTERNAL_CPLUSPLUS_LANG >= 201703L
  231. #endif // ABSL_BASE_INTERNAL_INVOKE_H_