invoke.h 7.5 KB

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