| 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 |