Index: base/memory/weak_ptr.h |
diff --git a/base/memory/weak_ptr.h b/base/memory/weak_ptr.h |
index 3544439dd3cafc9d8cc849a2cb4181cf70d2e947..f02362d908e71088b76fcae654cf7510f286166b 100644 |
--- a/base/memory/weak_ptr.h |
+++ b/base/memory/weak_ptr.h |
@@ -81,8 +81,30 @@ |
namespace base { |
-template <typename T> class SupportsWeakPtr; |
-template <typename T> class WeakPtr; |
+struct DefaultWeakPtrTraits { |
+ template <typename T> |
+ struct PointerHolder { |
+ protected: |
+ PointerHolder(T* ptr) : ptr_(ptr) {} |
+ void reset() { ptr_ = nullptr; } |
+ T* get() const { return ptr_; } |
+ |
+ private: |
+ T* ptr_; |
+ }; |
+ |
+ template <typename T> |
+ using PointerType = T*; |
+}; |
+ |
+template <typename T, typename Traits = DefaultWeakPtrTraits> |
+class SupportsWeakPtr; |
+ |
+template <typename T, typename Pointer = DefaultWeakPtrTraits> |
+class WeakPtr; |
+ |
+template <typename T, typename Pointer = DefaultWeakPtrTraits> |
+class WeakPtrFactory; |
namespace internal { |
// These classes are part of the WeakPtr implementation. |
@@ -164,35 +186,35 @@ class BASE_EXPORT WeakPtrBase { |
// otherwise get instantiated separately for each distinct instantiation of |
// SupportsWeakPtr<>. |
class SupportsWeakPtrBase { |
+ private: |
+ // This template function uses type inference to find a Base of Derived |
+ // which is an instance of SupportsWeakPtr<Base>. We can then safely |
+ // static_cast the Base* to a Derived*. |
+ template <typename Derived, typename Base, typename Traits> |
+ static WeakPtr<Derived, Traits> AsWeakPtrImpl( |
+ Derived* t, |
+ const SupportsWeakPtr<Base, Traits>&) { |
+ WeakPtr<Base, Traits> ptr = t->Base::AsWeakPtr(); |
+ return WeakPtr<Derived, Traits>(ptr.ref_, static_cast<Derived*>(ptr.get())); |
+ } |
+ |
public: |
// A safe static downcast of a WeakPtr<Base> to WeakPtr<Derived>. This |
// conversion will only compile if there is exists a Base which inherits |
// from SupportsWeakPtr<Base>. See base::AsWeakPtr() below for a helper |
// function that makes calling this easier. |
- template<typename Derived> |
- static WeakPtr<Derived> StaticAsWeakPtr(Derived* t) { |
+ template <typename Derived> |
+ static auto StaticAsWeakPtr(Derived* t) |
+ -> decltype(AsWeakPtrImpl<Derived>(t, *t)) { |
static_assert( |
std::is_base_of<internal::SupportsWeakPtrBase, Derived>::value, |
"AsWeakPtr argument must inherit from SupportsWeakPtr"); |
return AsWeakPtrImpl<Derived>(t, *t); |
} |
- |
- private: |
- // This template function uses type inference to find a Base of Derived |
- // which is an instance of SupportsWeakPtr<Base>. We can then safely |
- // static_cast the Base* to a Derived*. |
- template <typename Derived, typename Base> |
- static WeakPtr<Derived> AsWeakPtrImpl( |
- Derived* t, const SupportsWeakPtr<Base>&) { |
- WeakPtr<Base> ptr = t->Base::AsWeakPtr(); |
- return WeakPtr<Derived>(ptr.ref_, static_cast<Derived*>(ptr.ptr_)); |
- } |
}; |
} // namespace internal |
-template <typename T> class WeakPtrFactory; |
- |
// The WeakPtr class holds a weak reference to |T*|. |
// |
// This class is designed to be used like a normal pointer. You should always |
@@ -206,23 +228,30 @@ template <typename T> class WeakPtrFactory; |
// if (foo) |
// foo->method(); |
// |
-template <typename T> |
-class WeakPtr : public internal::WeakPtrBase { |
- public: |
- WeakPtr() : ptr_(nullptr) {} |
+template <typename T, typename Traits> |
+class WeakPtr : public internal::WeakPtrBase, |
+ public Traits::template PointerHolder<T> { |
+ private: |
+ using PointerHolder = typename Traits::template PointerHolder<T>; |
- WeakPtr(std::nullptr_t) : ptr_(nullptr) {} |
+ public: |
+ WeakPtr() : PointerHolder(nullptr) {} |
+ WeakPtr(std::nullptr_t) : PointerHolder(nullptr) {} |
// Allow conversion from U to T provided U "is a" T. Note that this |
// is separate from the (implicit) copy and move constructors. |
- template <typename U> |
- WeakPtr(const WeakPtr<U>& other) : WeakPtrBase(other), ptr_(other.ptr_) { |
+ template <typename U, typename OtherTraits> |
+ WeakPtr(const WeakPtr<U, OtherTraits>& other) |
+ : WeakPtrBase(other), PointerHolder(other.get()) {} |
+ template <typename U, typename OtherTraits> |
+ WeakPtr(WeakPtr<U, OtherTraits>&& other) |
+ : WeakPtrBase(std::move(other)), PointerHolder(other.get()) {} |
+ |
+ T* get() const { |
+ if (ref_.is_valid()) |
+ return PointerHolder::get(); |
+ return nullptr; |
} |
- template <typename U> |
- WeakPtr(WeakPtr<U>&& other) |
- : WeakPtrBase(std::move(other)), ptr_(other.ptr_) {} |
- |
- T* get() const { return ref_.is_valid() ? ptr_ : nullptr; } |
T& operator*() const { |
DCHECK(get() != nullptr); |
@@ -235,7 +264,7 @@ class WeakPtr : public internal::WeakPtrBase { |
void reset() { |
ref_ = internal::WeakReference(); |
- ptr_ = nullptr; |
+ PointerHolder::reset(); |
} |
// Allow conditionals to test validity, e.g. if (weak_ptr) {...}; |
@@ -243,35 +272,32 @@ class WeakPtr : public internal::WeakPtrBase { |
private: |
friend class internal::SupportsWeakPtrBase; |
- template <typename U> friend class WeakPtr; |
- friend class SupportsWeakPtr<T>; |
- friend class WeakPtrFactory<T>; |
- |
- WeakPtr(const internal::WeakReference& ref, T* ptr) |
- : WeakPtrBase(ref), |
- ptr_(ptr) { |
- } |
+ template <typename, typename> |
+ friend class WeakPtr; |
+ friend class SupportsWeakPtr<T, Traits>; |
+ friend class WeakPtrFactory<T, Traits>; |
// This pointer is only valid when ref_.is_valid() is true. Otherwise, its |
// value is undefined (as opposed to nullptr). |
- T* ptr_; |
+ WeakPtr(const internal::WeakReference& ref, T* ptr) |
+ : WeakPtrBase(ref), PointerHolder(std::move(ptr)) {} |
}; |
// Allow callers to compare WeakPtrs against nullptr to test validity. |
-template <class T> |
-bool operator!=(const WeakPtr<T>& weak_ptr, std::nullptr_t) { |
+template <typename T, typename Traits> |
+bool operator!=(const WeakPtr<T, Traits>& weak_ptr, std::nullptr_t) { |
return !(weak_ptr == nullptr); |
} |
-template <class T> |
-bool operator!=(std::nullptr_t, const WeakPtr<T>& weak_ptr) { |
+template <typename T, typename Traits> |
+bool operator!=(std::nullptr_t, const WeakPtr<T, Traits>& weak_ptr) { |
return weak_ptr != nullptr; |
} |
-template <class T> |
-bool operator==(const WeakPtr<T>& weak_ptr, std::nullptr_t) { |
+template <typename T, typename Traits> |
+bool operator==(const WeakPtr<T, Traits>& weak_ptr, std::nullptr_t) { |
return weak_ptr.get() == nullptr; |
} |
-template <class T> |
-bool operator==(std::nullptr_t, const WeakPtr<T>& weak_ptr) { |
+template <typename T, typename Traits> |
+bool operator==(std::nullptr_t, const WeakPtr<T, Traits>& weak_ptr) { |
return weak_ptr == nullptr; |
} |
@@ -280,34 +306,36 @@ bool operator==(std::nullptr_t, const WeakPtr<T>& weak_ptr) { |
// need weak pointers within the implementation of a class. This class is also |
// useful when working with primitive types. For example, you could have a |
// WeakPtrFactory<bool> that is used to pass around a weak reference to a bool. |
-template <class T> |
-class WeakPtrFactory { |
+template <typename T, typename Traits> |
+class WeakPtrFactory : public Traits::template PointerHolder<T> { |
+ private: |
+ using PointerHolder = typename Traits::template PointerHolder<T>; |
+ |
public: |
- explicit WeakPtrFactory(T* ptr) : ptr_(ptr) { |
- } |
+ explicit WeakPtrFactory(T* ptr) : PointerHolder(ptr) {} |
- ~WeakPtrFactory() { ptr_ = nullptr; } |
+ ~WeakPtrFactory() { PointerHolder::reset(); } |
- WeakPtr<T> GetWeakPtr() { |
- DCHECK(ptr_); |
- return WeakPtr<T>(weak_reference_owner_.GetRef(), ptr_); |
+ WeakPtr<T, Traits> GetWeakPtr() { |
+ DCHECK(PointerHolder::get()); |
+ return WeakPtr<T, Traits>(weak_reference_owner_.GetRef(), |
+ PointerHolder::get()); |
} |
// Call this method to invalidate all existing weak pointers. |
void InvalidateWeakPtrs() { |
- DCHECK(ptr_); |
+ DCHECK(PointerHolder::get()); |
weak_reference_owner_.Invalidate(); |
} |
// Call this method to determine if any weak pointers exist. |
bool HasWeakPtrs() const { |
- DCHECK(ptr_); |
+ DCHECK(PointerHolder::get()); |
return weak_reference_owner_.HasRefs(); |
} |
private: |
internal::WeakReferenceOwner weak_reference_owner_; |
- T* ptr_; |
DISALLOW_IMPLICIT_CONSTRUCTORS(WeakPtrFactory); |
}; |
@@ -316,13 +344,14 @@ class WeakPtrFactory { |
// pointers. However, since SupportsWeakPtr's destructor won't invalidate |
// weak pointers to the class until after the derived class' members have been |
// destroyed, its use can lead to subtle use-after-destroy issues. |
-template <class T> |
+template <typename T, typename Traits> |
class SupportsWeakPtr : public internal::SupportsWeakPtrBase { |
public: |
SupportsWeakPtr() {} |
- WeakPtr<T> AsWeakPtr() { |
- return WeakPtr<T>(weak_reference_owner_.GetRef(), static_cast<T*>(this)); |
+ WeakPtr<T, Traits> AsWeakPtr() { |
+ return WeakPtr<T, Traits>(weak_reference_owner_.GetRef(), |
+ static_cast<T*>(this)); |
} |
protected: |
@@ -352,7 +381,8 @@ class SupportsWeakPtr : public internal::SupportsWeakPtrBase { |
// base::WeakPtr<Derived> ptr = derived.AsWeakPtr(); // Fails. |
template <typename Derived> |
-WeakPtr<Derived> AsWeakPtr(Derived* t) { |
+auto AsWeakPtr(Derived* t) |
+ -> decltype(internal::SupportsWeakPtrBase::StaticAsWeakPtr<Derived>(t)) { |
return internal::SupportsWeakPtrBase::StaticAsWeakPtr<Derived>(t); |
} |