Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-12-16 09:40:42

0001 // Copyright 2017 The Abseil Authors.
0002 //
0003 // Licensed under the Apache License, Version 2.0 (the "License");
0004 // you may not use this file except in compliance with the License.
0005 // You may obtain a copy of the License at
0006 //
0007 //      https://www.apache.org/licenses/LICENSE-2.0
0008 //
0009 // Unless required by applicable law or agreed to in writing, software
0010 // distributed under the License is distributed on an "AS IS" BASIS,
0011 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0012 // See the License for the specific language governing permissions and
0013 // limitations under the License.
0014 //
0015 // absl::base_internal::invoke(f, args...) is an implementation of
0016 // INVOKE(f, args...) from section [func.require] of the C++ standard.
0017 // When compiled as C++17 and later versions, it is implemented as an alias of
0018 // std::invoke.
0019 //
0020 // [func.require]
0021 // Define INVOKE (f, t1, t2, ..., tN) as follows:
0022 // 1. (t1.*f)(t2, ..., tN) when f is a pointer to a member function of a class T
0023 //    and t1 is an object of type T or a reference to an object of type T or a
0024 //    reference to an object of a type derived from T;
0025 // 2. ((*t1).*f)(t2, ..., tN) when f is a pointer to a member function of a
0026 //    class T and t1 is not one of the types described in the previous item;
0027 // 3. t1.*f when N == 1 and f is a pointer to member data of a class T and t1 is
0028 //    an object of type T or a reference to an object of type T or a reference
0029 //    to an object of a type derived from T;
0030 // 4. (*t1).*f when N == 1 and f is a pointer to member data of a class T and t1
0031 //    is not one of the types described in the previous item;
0032 // 5. f(t1, t2, ..., tN) in all other cases.
0033 //
0034 // The implementation is SFINAE-friendly: substitution failure within invoke()
0035 // isn't an error.
0036 
0037 #ifndef ABSL_BASE_INTERNAL_INVOKE_H_
0038 #define ABSL_BASE_INTERNAL_INVOKE_H_
0039 
0040 #include "absl/base/config.h"
0041 
0042 #if ABSL_INTERNAL_CPLUSPLUS_LANG >= 201703L
0043 
0044 #include <functional>
0045 
0046 namespace absl {
0047 ABSL_NAMESPACE_BEGIN
0048 namespace base_internal {
0049 
0050 using std::invoke;
0051 using std::invoke_result_t;
0052 using std::is_invocable_r;
0053 
0054 }  // namespace base_internal
0055 ABSL_NAMESPACE_END
0056 }  // namespace absl
0057 
0058 #else  // ABSL_INTERNAL_CPLUSPLUS_LANG >= 201703L
0059 
0060 #include <algorithm>
0061 #include <type_traits>
0062 #include <utility>
0063 
0064 #include "absl/meta/type_traits.h"
0065 
0066 // The following code is internal implementation detail.  See the comment at the
0067 // top of this file for the API documentation.
0068 
0069 namespace absl {
0070 ABSL_NAMESPACE_BEGIN
0071 namespace base_internal {
0072 
0073 // The five classes below each implement one of the clauses from the definition
0074 // of INVOKE. The inner class template Accept<F, Args...> checks whether the
0075 // clause is applicable; static function template Invoke(f, args...) does the
0076 // invocation.
0077 //
0078 // By separating the clause selection logic from invocation we make sure that
0079 // Invoke() does exactly what the standard says.
0080 
0081 template <typename Derived>
0082 struct StrippedAccept {
0083   template <typename... Args>
0084   struct Accept : Derived::template AcceptImpl<typename std::remove_cv<
0085                       typename std::remove_reference<Args>::type>::type...> {};
0086 };
0087 
0088 // (t1.*f)(t2, ..., tN) when f is a pointer to a member function of a class T
0089 // and t1 is an object of type T or a reference to an object of type T or a
0090 // reference to an object of a type derived from T.
0091 struct MemFunAndRef : StrippedAccept<MemFunAndRef> {
0092   template <typename... Args>
0093   struct AcceptImpl : std::false_type {};
0094 
0095   template <typename MemFunType, typename C, typename Obj, typename... Args>
0096   struct AcceptImpl<MemFunType C::*, Obj, Args...>
0097       : std::integral_constant<bool, std::is_base_of<C, Obj>::value &&
0098                                          absl::is_function<MemFunType>::value> {
0099   };
0100 
0101   template <typename MemFun, typename Obj, typename... Args>
0102   static decltype((std::declval<Obj>().*
0103                    std::declval<MemFun>())(std::declval<Args>()...))
0104   Invoke(MemFun&& mem_fun, Obj&& obj, Args&&... args) {
0105 // Ignore bogus GCC warnings on this line.
0106 // See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=101436 for similar example.
0107 #if ABSL_INTERNAL_HAVE_MIN_GNUC_VERSION(11, 0)
0108 #pragma GCC diagnostic push
0109 #pragma GCC diagnostic ignored "-Warray-bounds"
0110 #pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
0111 #endif
0112     return (std::forward<Obj>(obj).*
0113             std::forward<MemFun>(mem_fun))(std::forward<Args>(args)...);
0114 #if ABSL_INTERNAL_HAVE_MIN_GNUC_VERSION(11, 0)
0115 #pragma GCC diagnostic pop
0116 #endif
0117   }
0118 };
0119 
0120 // ((*t1).*f)(t2, ..., tN) when f is a pointer to a member function of a
0121 // class T and t1 is not one of the types described in the previous item.
0122 struct MemFunAndPtr : StrippedAccept<MemFunAndPtr> {
0123   template <typename... Args>
0124   struct AcceptImpl : std::false_type {};
0125 
0126   template <typename MemFunType, typename C, typename Ptr, typename... Args>
0127   struct AcceptImpl<MemFunType C::*, Ptr, Args...>
0128       : std::integral_constant<bool, !std::is_base_of<C, Ptr>::value &&
0129                                          absl::is_function<MemFunType>::value> {
0130   };
0131 
0132   template <typename MemFun, typename Ptr, typename... Args>
0133   static decltype(((*std::declval<Ptr>()).*
0134                    std::declval<MemFun>())(std::declval<Args>()...))
0135   Invoke(MemFun&& mem_fun, Ptr&& ptr, Args&&... args) {
0136     return ((*std::forward<Ptr>(ptr)).*
0137             std::forward<MemFun>(mem_fun))(std::forward<Args>(args)...);
0138   }
0139 };
0140 
0141 // t1.*f when N == 1 and f is a pointer to member data of a class T and t1 is
0142 // an object of type T or a reference to an object of type T or a reference
0143 // to an object of a type derived from T.
0144 struct DataMemAndRef : StrippedAccept<DataMemAndRef> {
0145   template <typename... Args>
0146   struct AcceptImpl : std::false_type {};
0147 
0148   template <typename R, typename C, typename Obj>
0149   struct AcceptImpl<R C::*, Obj>
0150       : std::integral_constant<bool, std::is_base_of<C, Obj>::value &&
0151                                          !absl::is_function<R>::value> {};
0152 
0153   template <typename DataMem, typename Ref>
0154   static decltype(std::declval<Ref>().*std::declval<DataMem>()) Invoke(
0155       DataMem&& data_mem, Ref&& ref) {
0156     return std::forward<Ref>(ref).*std::forward<DataMem>(data_mem);
0157   }
0158 };
0159 
0160 // (*t1).*f when N == 1 and f is a pointer to member data of a class T and t1
0161 // is not one of the types described in the previous item.
0162 struct DataMemAndPtr : StrippedAccept<DataMemAndPtr> {
0163   template <typename... Args>
0164   struct AcceptImpl : std::false_type {};
0165 
0166   template <typename R, typename C, typename Ptr>
0167   struct AcceptImpl<R C::*, Ptr>
0168       : std::integral_constant<bool, !std::is_base_of<C, Ptr>::value &&
0169                                          !absl::is_function<R>::value> {};
0170 
0171   template <typename DataMem, typename Ptr>
0172   static decltype((*std::declval<Ptr>()).*std::declval<DataMem>()) Invoke(
0173       DataMem&& data_mem, Ptr&& ptr) {
0174     return (*std::forward<Ptr>(ptr)).*std::forward<DataMem>(data_mem);
0175   }
0176 };
0177 
0178 // f(t1, t2, ..., tN) in all other cases.
0179 struct Callable {
0180   // Callable doesn't have Accept because it's the last clause that gets picked
0181   // when none of the previous clauses are applicable.
0182   template <typename F, typename... Args>
0183   static decltype(std::declval<F>()(std::declval<Args>()...)) Invoke(
0184       F&& f, Args&&... args) {
0185     return std::forward<F>(f)(std::forward<Args>(args)...);
0186   }
0187 };
0188 
0189 // Resolves to the first matching clause.
0190 template <typename... Args>
0191 struct Invoker {
0192   typedef typename std::conditional<
0193       MemFunAndRef::Accept<Args...>::value, MemFunAndRef,
0194       typename std::conditional<
0195           MemFunAndPtr::Accept<Args...>::value, MemFunAndPtr,
0196           typename std::conditional<
0197               DataMemAndRef::Accept<Args...>::value, DataMemAndRef,
0198               typename std::conditional<DataMemAndPtr::Accept<Args...>::value,
0199                                         DataMemAndPtr, Callable>::type>::type>::
0200           type>::type type;
0201 };
0202 
0203 // The result type of Invoke<F, Args...>.
0204 template <typename F, typename... Args>
0205 using invoke_result_t = decltype(Invoker<F, Args...>::type::Invoke(
0206     std::declval<F>(), std::declval<Args>()...));
0207 
0208 // Invoke(f, args...) is an implementation of INVOKE(f, args...) from section
0209 // [func.require] of the C++ standard.
0210 template <typename F, typename... Args>
0211 invoke_result_t<F, Args...> invoke(F&& f, Args&&... args) {
0212   return Invoker<F, Args...>::type::Invoke(std::forward<F>(f),
0213                                            std::forward<Args>(args)...);
0214 }
0215 
0216 template <typename AlwaysVoid, typename, typename, typename...>
0217 struct IsInvocableRImpl : std::false_type {};
0218 
0219 template <typename R, typename F, typename... Args>
0220 struct IsInvocableRImpl<
0221     absl::void_t<absl::base_internal::invoke_result_t<F, Args...> >, R, F,
0222     Args...>
0223     : std::integral_constant<
0224           bool,
0225           std::is_convertible<absl::base_internal::invoke_result_t<F, Args...>,
0226                               R>::value ||
0227               std::is_void<R>::value> {};
0228 
0229 // Type trait whose member `value` is true if invoking `F` with `Args` is valid,
0230 // and either the return type is convertible to `R`, or `R` is void.
0231 // C++11-compatible version of `std::is_invocable_r`.
0232 template <typename R, typename F, typename... Args>
0233 using is_invocable_r = IsInvocableRImpl<void, R, F, Args...>;
0234 
0235 }  // namespace base_internal
0236 ABSL_NAMESPACE_END
0237 }  // namespace absl
0238 
0239 #endif  // ABSL_INTERNAL_CPLUSPLUS_LANG >= 201703L
0240 
0241 #endif  // ABSL_BASE_INTERNAL_INVOKE_H_