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