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