invoke.h 9.2 KB

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