OLD | NEW |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 // This defines a set of argument wrappers and related factory methods that | 5 // This defines a set of argument wrappers and related factory methods that |
6 // can be used specify the refcounting and reference semantics of arguments | 6 // can be used specify the refcounting and reference semantics of arguments |
7 // that are bound by the Bind() function in base/bind.h. | 7 // that are bound by the Bind() function in base/bind.h. |
8 // | 8 // |
9 // It also defines a set of simple functions and utilities that people want | 9 // It also defines a set of simple functions and utilities that people want |
10 // when using Callback<> and Bind(). | 10 // when using Callback<> and Bind(). |
(...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
169 #include "base/memory/weak_ptr.h" | 169 #include "base/memory/weak_ptr.h" |
170 #include "build/build_config.h" | 170 #include "build/build_config.h" |
171 | 171 |
172 namespace base { | 172 namespace base { |
173 | 173 |
174 template <typename T> | 174 template <typename T> |
175 struct IsWeakReceiver; | 175 struct IsWeakReceiver; |
176 | 176 |
177 namespace internal { | 177 namespace internal { |
178 | 178 |
179 // Use the Substitution Failure Is Not An Error (SFINAE) trick to inspect T | |
180 // for the existence of AddRef() and Release() functions of the correct | |
181 // signature. | |
182 // | |
183 // http://en.wikipedia.org/wiki/Substitution_failure_is_not_an_error | |
184 // http://stackoverflow.com/questions/257288/is-it-possible-to-write-a-c-templat
e-to-check-for-a-functions-existence | |
185 // http://stackoverflow.com/questions/4358584/sfinae-approach-comparison | |
186 // http://stackoverflow.com/questions/1966362/sfinae-to-check-for-inherited-memb
er-functions | |
187 // | |
188 // The last link in particular show the method used below. | |
189 // | |
190 // For SFINAE to work with inherited methods, we need to pull some extra tricks | |
191 // with multiple inheritance. In the more standard formulation, the overloads | |
192 // of Check would be: | |
193 // | |
194 // template <typename C> | |
195 // Yes NotTheCheckWeWant(Helper<&C::TargetFunc>*); | |
196 // | |
197 // template <typename C> | |
198 // No NotTheCheckWeWant(...); | |
199 // | |
200 // static const bool value = sizeof(NotTheCheckWeWant<T>(0)) == sizeof(Yes); | |
201 // | |
202 // The problem here is that template resolution will not match | |
203 // C::TargetFunc if TargetFunc does not exist directly in C. That is, if | |
204 // TargetFunc in inherited from an ancestor, &C::TargetFunc will not match, | |
205 // |value| will be false. This formulation only checks for whether or | |
206 // not TargetFunc exist directly in the class being introspected. | |
207 // | |
208 // To get around this, we play a dirty trick with multiple inheritance. | |
209 // First, We create a class BaseMixin that declares each function that we | |
210 // want to probe for. Then we create a class Base that inherits from both T | |
211 // (the class we wish to probe) and BaseMixin. Note that the function | |
212 // signature in BaseMixin does not need to match the signature of the function | |
213 // we are probing for; thus it's easiest to just use void(). | |
214 // | |
215 // Now, if TargetFunc exists somewhere in T, then &Base::TargetFunc has an | |
216 // ambiguous resolution between BaseMixin and T. This lets us write the | |
217 // following: | |
218 // | |
219 // template <typename C> | |
220 // No GoodCheck(Helper<&C::TargetFunc>*); | |
221 // | |
222 // template <typename C> | |
223 // Yes GoodCheck(...); | |
224 // | |
225 // static const bool value = sizeof(GoodCheck<Base>(0)) == sizeof(Yes); | |
226 // | |
227 // Notice here that the variadic version of GoodCheck() returns Yes here | |
228 // instead of No like the previous one. Also notice that we calculate |value| | |
229 // by specializing GoodCheck() on Base instead of T. | |
230 // | |
231 // We've reversed the roles of the variadic, and Helper overloads. | |
232 // GoodCheck(Helper<&C::TargetFunc>*), when C = Base, fails to be a valid | |
233 // substitution if T::TargetFunc exists. Thus GoodCheck<Base>(0) will resolve | |
234 // to the variadic version if T has TargetFunc. If T::TargetFunc does not | |
235 // exist, then &C::TargetFunc is not ambiguous, and the overload resolution | |
236 // will prefer GoodCheck(Helper<&C::TargetFunc>*). | |
237 // | |
238 // This method of SFINAE will correctly probe for inherited names, but it cannot | |
239 // typecheck those names. It's still a good enough sanity check though. | |
240 // | |
241 // Works on gcc-4.2, gcc-4.4, and Visual Studio 2008. | |
242 // | |
243 | |
244 template <typename T> | |
245 class HasIsMethodTag { | |
246 using Yes = char[1]; | |
247 using No = char[2]; | |
248 | |
249 template <typename U> | |
250 static Yes& Check(typename U::IsMethod*); | |
251 | |
252 template <typename U> | |
253 static No& Check(...); | |
254 | |
255 public: | |
256 enum { value = sizeof(Check<T>(0)) == sizeof(Yes) }; | |
257 }; | |
258 | |
259 template <typename T> | 179 template <typename T> |
260 class UnretainedWrapper { | 180 class UnretainedWrapper { |
261 public: | 181 public: |
262 explicit UnretainedWrapper(T* o) : ptr_(o) {} | 182 explicit UnretainedWrapper(T* o) : ptr_(o) {} |
263 T* get() const { return ptr_; } | 183 T* get() const { return ptr_; } |
264 private: | 184 private: |
265 T* ptr_; | 185 T* ptr_; |
266 }; | 186 }; |
267 | 187 |
268 template <typename T> | 188 template <typename T> |
(...skipping 11 matching lines...) Expand all Loading... |
280 explicit RetainedRefWrapper(T* o) : ptr_(o) {} | 200 explicit RetainedRefWrapper(T* o) : ptr_(o) {} |
281 explicit RetainedRefWrapper(scoped_refptr<T> o) : ptr_(std::move(o)) {} | 201 explicit RetainedRefWrapper(scoped_refptr<T> o) : ptr_(std::move(o)) {} |
282 T* get() const { return ptr_.get(); } | 202 T* get() const { return ptr_.get(); } |
283 private: | 203 private: |
284 scoped_refptr<T> ptr_; | 204 scoped_refptr<T> ptr_; |
285 }; | 205 }; |
286 | 206 |
287 template <typename T> | 207 template <typename T> |
288 struct IgnoreResultHelper { | 208 struct IgnoreResultHelper { |
289 explicit IgnoreResultHelper(T functor) : functor_(std::move(functor)) {} | 209 explicit IgnoreResultHelper(T functor) : functor_(std::move(functor)) {} |
| 210 explicit operator bool() const { return !!functor_; } |
290 | 211 |
291 T functor_; | 212 T functor_; |
292 }; | 213 }; |
293 | 214 |
294 // An alternate implementation is to avoid the destructive copy, and instead | 215 // An alternate implementation is to avoid the destructive copy, and instead |
295 // specialize ParamTraits<> for OwnedWrapper<> to change the StorageType to | 216 // specialize ParamTraits<> for OwnedWrapper<> to change the StorageType to |
296 // a class that is essentially a std::unique_ptr<>. | 217 // a class that is essentially a std::unique_ptr<>. |
297 // | 218 // |
298 // The current implementation has the benefit though of leaving ParamTraits<> | 219 // The current implementation has the benefit though of leaving ParamTraits<> |
299 // fully in callback_internal.h as well as avoiding type conversions during | 220 // fully in callback_internal.h as well as avoiding type conversions during |
(...skipping 272 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
572 | 493 |
573 template <typename T> | 494 template <typename T> |
574 struct IsWeakReceiver<internal::ConstRefWrapper<T>> : IsWeakReceiver<T> {}; | 495 struct IsWeakReceiver<internal::ConstRefWrapper<T>> : IsWeakReceiver<T> {}; |
575 | 496 |
576 template <typename T> | 497 template <typename T> |
577 struct IsWeakReceiver<WeakPtr<T>> : std::true_type {}; | 498 struct IsWeakReceiver<WeakPtr<T>> : std::true_type {}; |
578 | 499 |
579 } // namespace base | 500 } // namespace base |
580 | 501 |
581 #endif // BASE_BIND_HELPERS_H_ | 502 #endif // BASE_BIND_HELPERS_H_ |
OLD | NEW |