invoke.h
Go to the documentation of this file.
00001 // Copyright 2017 The Abseil Authors.
00002 //
00003 // Licensed under the Apache License, Version 2.0 (the "License");
00004 // you may not use this file except in compliance with the License.
00005 // You may obtain a copy of the License at
00006 //
00007 //      https://www.apache.org/licenses/LICENSE-2.0
00008 //
00009 // Unless required by applicable law or agreed to in writing, software
00010 // distributed under the License is distributed on an "AS IS" BASIS,
00011 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00012 // See the License for the specific language governing permissions and
00013 // limitations under the License.
00014 //
00015 // absl::base_internal::Invoke(f, args...) is an implementation of
00016 // INVOKE(f, args...) from section [func.require] of the C++ standard.
00017 //
00018 // [func.require]
00019 // Define INVOKE (f, t1, t2, ..., tN) as follows:
00020 // 1. (t1.*f)(t2, ..., tN) when f is a pointer to a member function of a class T
00021 //    and t1 is an object of type T or a reference to an object of type T or a
00022 //    reference to an object of a type derived from T;
00023 // 2. ((*t1).*f)(t2, ..., tN) when f is a pointer to a member function of a
00024 //    class T and t1 is not one of the types described in the previous item;
00025 // 3. t1.*f when N == 1 and f is a pointer to member data of a class T and t1 is
00026 //    an object of type T or a reference to an object of type T or a reference
00027 //    to an object of a type derived from T;
00028 // 4. (*t1).*f when N == 1 and f is a pointer to member data of a class T and t1
00029 //    is not one of the types described in the previous item;
00030 // 5. f(t1, t2, ..., tN) in all other cases.
00031 //
00032 // The implementation is SFINAE-friendly: substitution failure within Invoke()
00033 // isn't an error.
00034 
00035 #ifndef ABSL_BASE_INTERNAL_INVOKE_H_
00036 #define ABSL_BASE_INTERNAL_INVOKE_H_
00037 
00038 #include <algorithm>
00039 #include <type_traits>
00040 #include <utility>
00041 
00042 // The following code is internal implementation detail.  See the comment at the
00043 // top of this file for the API documentation.
00044 
00045 namespace absl {
00046 namespace base_internal {
00047 
00048 // The five classes below each implement one of the clauses from the definition
00049 // of INVOKE. The inner class template Accept<F, Args...> checks whether the
00050 // clause is applicable; static function template Invoke(f, args...) does the
00051 // invocation.
00052 //
00053 // By separating the clause selection logic from invocation we make sure that
00054 // Invoke() does exactly what the standard says.
00055 
00056 template <typename Derived>
00057 struct StrippedAccept {
00058   template <typename... Args>
00059   struct Accept : Derived::template AcceptImpl<typename std::remove_cv<
00060                       typename std::remove_reference<Args>::type>::type...> {};
00061 };
00062 
00063 // (t1.*f)(t2, ..., tN) when f is a pointer to a member function of a class T
00064 // and t1 is an object of type T or a reference to an object of type T or a
00065 // reference to an object of a type derived from T.
00066 struct MemFunAndRef : StrippedAccept<MemFunAndRef> {
00067   template <typename... Args>
00068   struct AcceptImpl : std::false_type {};
00069 
00070   template <typename R, typename C, typename... Params, typename Obj,
00071             typename... Args>
00072   struct AcceptImpl<R (C::*)(Params...), Obj, Args...>
00073       : std::is_base_of<C, Obj> {};
00074 
00075   template <typename R, typename C, typename... Params, typename Obj,
00076             typename... Args>
00077   struct AcceptImpl<R (C::*)(Params...) const, Obj, Args...>
00078       : std::is_base_of<C, Obj> {};
00079 
00080   template <typename MemFun, typename Obj, typename... Args>
00081   static decltype((std::declval<Obj>().*
00082                    std::declval<MemFun>())(std::declval<Args>()...))
00083   Invoke(MemFun&& mem_fun, Obj&& obj, Args&&... args) {
00084     return (std::forward<Obj>(obj).*
00085             std::forward<MemFun>(mem_fun))(std::forward<Args>(args)...);
00086   }
00087 };
00088 
00089 // ((*t1).*f)(t2, ..., tN) when f is a pointer to a member function of a
00090 // class T and t1 is not one of the types described in the previous item.
00091 struct MemFunAndPtr : StrippedAccept<MemFunAndPtr> {
00092   template <typename... Args>
00093   struct AcceptImpl : std::false_type {};
00094 
00095   template <typename R, typename C, typename... Params, typename Ptr,
00096             typename... Args>
00097   struct AcceptImpl<R (C::*)(Params...), Ptr, Args...>
00098       : std::integral_constant<bool, !std::is_base_of<C, Ptr>::value> {};
00099 
00100   template <typename R, typename C, typename... Params, typename Ptr,
00101             typename... Args>
00102   struct AcceptImpl<R (C::*)(Params...) const, Ptr, Args...>
00103       : std::integral_constant<bool, !std::is_base_of<C, Ptr>::value> {};
00104 
00105   template <typename MemFun, typename Ptr, typename... Args>
00106   static decltype(((*std::declval<Ptr>()).*
00107                    std::declval<MemFun>())(std::declval<Args>()...))
00108   Invoke(MemFun&& mem_fun, Ptr&& ptr, Args&&... args) {
00109     return ((*std::forward<Ptr>(ptr)).*
00110             std::forward<MemFun>(mem_fun))(std::forward<Args>(args)...);
00111   }
00112 };
00113 
00114 // t1.*f when N == 1 and f is a pointer to member data of a class T and t1 is
00115 // an object of type T or a reference to an object of type T or a reference
00116 // to an object of a type derived from T.
00117 struct DataMemAndRef : StrippedAccept<DataMemAndRef> {
00118   template <typename... Args>
00119   struct AcceptImpl : std::false_type {};
00120 
00121   template <typename R, typename C, typename Obj>
00122   struct AcceptImpl<R C::*, Obj> : std::is_base_of<C, Obj> {};
00123 
00124   template <typename DataMem, typename Ref>
00125   static decltype(std::declval<Ref>().*std::declval<DataMem>()) Invoke(
00126       DataMem&& data_mem, Ref&& ref) {
00127     return std::forward<Ref>(ref).*std::forward<DataMem>(data_mem);
00128   }
00129 };
00130 
00131 // (*t1).*f when N == 1 and f is a pointer to member data of a class T and t1
00132 // is not one of the types described in the previous item.
00133 struct DataMemAndPtr : StrippedAccept<DataMemAndPtr> {
00134   template <typename... Args>
00135   struct AcceptImpl : std::false_type {};
00136 
00137   template <typename R, typename C, typename Ptr>
00138   struct AcceptImpl<R C::*, Ptr>
00139       : std::integral_constant<bool, !std::is_base_of<C, Ptr>::value> {};
00140 
00141   template <typename DataMem, typename Ptr>
00142   static decltype((*std::declval<Ptr>()).*std::declval<DataMem>()) Invoke(
00143       DataMem&& data_mem, Ptr&& ptr) {
00144     return (*std::forward<Ptr>(ptr)).*std::forward<DataMem>(data_mem);
00145   }
00146 };
00147 
00148 // f(t1, t2, ..., tN) in all other cases.
00149 struct Callable {
00150   // Callable doesn't have Accept because it's the last clause that gets picked
00151   // when none of the previous clauses are applicable.
00152   template <typename F, typename... Args>
00153   static decltype(std::declval<F>()(std::declval<Args>()...)) Invoke(
00154       F&& f, Args&&... args) {
00155     return std::forward<F>(f)(std::forward<Args>(args)...);
00156   }
00157 };
00158 
00159 // Resolves to the first matching clause.
00160 template <typename... Args>
00161 struct Invoker {
00162   typedef typename std::conditional<
00163       MemFunAndRef::Accept<Args...>::value, MemFunAndRef,
00164       typename std::conditional<
00165           MemFunAndPtr::Accept<Args...>::value, MemFunAndPtr,
00166           typename std::conditional<
00167               DataMemAndRef::Accept<Args...>::value, DataMemAndRef,
00168               typename std::conditional<DataMemAndPtr::Accept<Args...>::value,
00169                                         DataMemAndPtr, Callable>::type>::type>::
00170           type>::type type;
00171 };
00172 
00173 // The result type of Invoke<F, Args...>.
00174 template <typename F, typename... Args>
00175 using InvokeT = decltype(Invoker<F, Args...>::type::Invoke(
00176     std::declval<F>(), std::declval<Args>()...));
00177 
00178 // Invoke(f, args...) is an implementation of INVOKE(f, args...) from section
00179 // [func.require] of the C++ standard.
00180 template <typename F, typename... Args>
00181 InvokeT<F, Args...> Invoke(F&& f, Args&&... args) {
00182   return Invoker<F, Args...>::type::Invoke(std::forward<F>(f),
00183                                            std::forward<Args>(args)...);
00184 }
00185 }  // namespace base_internal
00186 }  // namespace absl
00187 
00188 #endif  // ABSL_BASE_INTERNAL_INVOKE_H_


abseil_cpp
Author(s):
autogenerated on Wed Jun 19 2019 19:42:15