Index: include/core/SkRefCnt.h |
diff --git a/include/core/SkRefCnt.h b/include/core/SkRefCnt.h |
index d33117751e0717943ec28b890bd645e98ff8f6bc..c3f724fa8ded11926e8f94e16d9e6e8e174d8cae 100644 |
--- a/include/core/SkRefCnt.h |
+++ b/include/core/SkRefCnt.h |
@@ -11,6 +11,7 @@ |
#include "../private/SkAtomics.h" |
#include "../private/SkUniquePtr.h" |
#include "SkTypes.h" |
+#include <functional> |
#include <utility> |
/** \class SkRefCntBase |
@@ -241,6 +242,8 @@ template <typename T> class sk_sp { |
/** Supports safe bool idiom. Obsolete with explicit operator bool. */ |
using unspecified_bool_type = T* sk_sp::*; |
public: |
+ using element_type = T; |
+ |
sk_sp() : fPtr(nullptr) {} |
sk_sp(std::nullptr_t) : fPtr(nullptr) {} |
@@ -249,8 +252,7 @@ public: |
* created sk_sp both have a reference to it. |
*/ |
sk_sp(const sk_sp<T>& that) : fPtr(SkSafeRef(that.get())) {} |
- template <typename U, |
- typename = skstd::enable_if_t<skstd::is_convertible<U*, T*>::value>> |
+ template <typename U, typename = skstd::enable_if_t<skstd::is_convertible<U*, T*>::value>> |
sk_sp(const sk_sp<U>& that) : fPtr(SkSafeRef(that.get())) {} |
/** |
@@ -259,8 +261,7 @@ public: |
* No call to ref() or unref() will be made. |
*/ |
sk_sp(sk_sp<T>&& that) : fPtr(that.release()) {} |
- template <typename U, |
- typename = skstd::enable_if_t<skstd::is_convertible<U*, T*>::value>> |
+ template <typename U, typename = skstd::enable_if_t<skstd::is_convertible<U*, T*>::value>> |
sk_sp(sk_sp<U>&& that) : fPtr(that.release()) {} |
/** |
@@ -274,6 +275,7 @@ public: |
*/ |
~sk_sp() { |
SkSafeUnref(fPtr); |
+ SkDEBUGCODE(fPtr = nullptr); |
} |
sk_sp<T>& operator=(std::nullptr_t) { this->reset(); return *this; } |
@@ -287,8 +289,7 @@ public: |
this->reset(SkSafeRef(that.get())); |
return *this; |
} |
- template <typename U, |
- typename = skstd::enable_if_t<skstd::is_convertible<U*, T*>::value>> |
+ template <typename U, typename = skstd::enable_if_t<skstd::is_convertible<U*, T*>::value>> |
sk_sp<T>& operator=(const sk_sp<U>& that) { |
this->reset(SkSafeRef(that.get())); |
return *this; |
@@ -303,21 +304,12 @@ public: |
this->reset(that.release()); |
return *this; |
} |
- template <typename U, |
- typename = skstd::enable_if_t<skstd::is_convertible<U*, T*>::value>> |
+ template <typename U, typename = skstd::enable_if_t<skstd::is_convertible<U*, T*>::value>> |
sk_sp<T>& operator=(sk_sp<U>&& that) { |
this->reset(that.release()); |
return *this; |
} |
- bool operator==(std::nullptr_t) const { return this->get() == nullptr; } |
- bool operator!=(std::nullptr_t) const { return this->get() != nullptr; } |
- |
- template <typename U> |
- bool operator==(const sk_sp<U>& that) const { return this->get() == that.get(); } |
- template <typename U> |
- bool operator!=(const sk_sp<U>& that) const { return this->get() != that.get(); } |
- |
T& operator*() const { |
SkASSERT(this->get() != nullptr); |
return *this->get(); |
@@ -338,8 +330,12 @@ public: |
* No call to ref() will be made. |
*/ |
void reset(T* ptr = nullptr) { |
- SkSafeUnref(fPtr); |
+ // Calling fPtr->unref() may call this->~() or this->reset(T*). |
+ // http://wg21.cmeerw.net/lwg/issue998 |
+ // http://wg21.cmeerw.net/lwg/issue2262 |
+ T* oldPtr = fPtr; |
fPtr = ptr; |
+ SkSafeUnref(oldPtr); |
} |
/** |
@@ -353,10 +349,82 @@ public: |
return ptr; |
} |
+ void swap(sk_sp<T>& that) /*noexcept*/ { |
+ using std::swap; |
+ swap(fPtr, that.fPtr); |
+ } |
+ |
private: |
T* fPtr; |
}; |
+template <typename T> inline void swap(sk_sp<T>& a, sk_sp<T>& b) /*noexcept*/ { |
+ a.swap(b); |
+} |
+ |
+template <typename T, typename U> inline bool operator==(const sk_sp<T>& a, const sk_sp<U>& b) { |
+ return a.get() == b.get(); |
+} |
+template <typename T> inline bool operator==(const sk_sp<T>& a, std::nullptr_t) /*noexcept*/ { |
+ return !a; |
+} |
+template <typename T> inline bool operator==(std::nullptr_t, const sk_sp<T>& b) /*noexcept*/ { |
+ return !b; |
+} |
+ |
+template <typename T, typename U> inline bool operator!=(const sk_sp<T>& a, const sk_sp<U>& b) { |
+ return a.get() != b.get(); |
+} |
+template <typename T> inline bool operator!=(const sk_sp<T>& a, std::nullptr_t) /*noexcept*/ { |
+ return static_cast<bool>(a); |
+} |
+template <typename T> inline bool operator!=(std::nullptr_t, const sk_sp<T>& b) /*noexcept*/ { |
+ return static_cast<bool>(b); |
+} |
+ |
+template <typename T, typename U> inline bool operator<(const sk_sp<T>& a, const sk_sp<U>& b) { |
+ // Provide defined total order on sk_sp. |
+ // http://wg21.cmeerw.net/lwg/issue1297 |
+ // http://wg21.cmeerw.net/lwg/issue1401 . |
+ return std::less<skstd::common_type_t<T*, U*>>()(a.get(), b.get()); |
+} |
+template <typename T> inline bool operator<(const sk_sp<T>& a, std::nullptr_t) { |
+ return std::less<T*>()(a.get(), nullptr); |
+} |
+template <typename T> inline bool operator<(std::nullptr_t, const sk_sp<T>& b) { |
+ return std::less<T*>()(nullptr, b.get()); |
+} |
+ |
+template <typename T, typename U> inline bool operator<=(const sk_sp<T>& a, const sk_sp<U>& b) { |
+ return !(b < a); |
+} |
+template <typename T> inline bool operator<=(const sk_sp<T>& a, std::nullptr_t) { |
+ return !(nullptr < a); |
+} |
+template <typename T> inline bool operator<=(std::nullptr_t, const sk_sp<T>& b) { |
+ return !(b < nullptr); |
+} |
+ |
+template <typename T, typename U> inline bool operator>(const sk_sp<T>& a, const sk_sp<U>& b) { |
+ return b < a; |
+} |
+template <typename T> inline bool operator>(const sk_sp<T>& a, std::nullptr_t) { |
+ return nullptr < a; |
+} |
+template <typename T> inline bool operator>(std::nullptr_t, const sk_sp<T>& b) { |
+ return b < nullptr; |
+} |
+ |
+template <typename T, typename U> inline bool operator>=(const sk_sp<T>& a, const sk_sp<U>& b) { |
+ return !(a < b); |
+} |
+template <typename T> inline bool operator>=(const sk_sp<T>& a, std::nullptr_t) { |
+ return !(a < nullptr); |
+} |
+template <typename T> inline bool operator>=(std::nullptr_t, const sk_sp<T>& b) { |
+ return !(nullptr < b); |
+} |
+ |
template <typename T, typename... Args> |
sk_sp<T> sk_make_sp(Args&&... args) { |
return sk_sp<T>(new T(std::forward<Args>(args)...)); |