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