diff --git a/include/core/SkRefCnt.h b/include/core/SkRefCnt.h index e2cf4456f8..02df993261 100644 --- a/include/core/SkRefCnt.h +++ b/include/core/SkRefCnt.h @@ -247,6 +247,9 @@ public: * created sk_sp both have a reference to it. */ sk_sp(const sk_sp& that) : fPtr(SkSafeRef(that.get())) {} + template ::value>> + sk_sp(const sk_sp& that) : fPtr(SkSafeRef(that.get())) {} /** * Move the underlying object from the argument to the newly created sk_sp. Afterwards only @@ -254,6 +257,9 @@ public: * No call to ref() or unref() will be made. */ sk_sp(sk_sp&& that) : fPtr(that.release()) {} + template ::value>> + sk_sp(sk_sp&& that) : fPtr(that.release()) {} /** * Adopt the bare pointer into the newly created sk_sp. @@ -268,7 +274,7 @@ public: SkSafeUnref(fPtr); } - sk_sp& operator=(std::nullptr_t) { this->reset(); } + sk_sp& operator=(std::nullptr_t) { this->reset(); return *this; } /** * Shares the underlying object referenced by the argument by calling ref() on it. If this @@ -279,6 +285,12 @@ public: this->reset(SkSafeRef(that.get())); return *this; } + template ::value>> + sk_sp& operator=(const sk_sp& that) { + this->reset(SkSafeRef(that.get())); + return *this; + } /** * Move the underlying object from the argument to the sk_sp. If the sk_sp previously held @@ -289,12 +301,20 @@ public: this->reset(that.release()); return *this; } + template ::value>> + sk_sp& operator=(sk_sp&& 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; } - bool operator==(const sk_sp& that) const { return this->get() == that.get(); } - bool operator!=(const sk_sp& that) const { return this->get() != that.get(); } + template + bool operator==(const sk_sp& that) const { return this->get() == that.get(); } + template + bool operator!=(const sk_sp& that) const { return this->get() != that.get(); } explicit operator bool() const { return this->get() != nullptr; } diff --git a/tests/RefCntTest.cpp b/tests/RefCntTest.cpp index e9d582d809..bda45317bc 100644 --- a/tests/RefCntTest.cpp +++ b/tests/RefCntTest.cpp @@ -134,11 +134,26 @@ public: } }; -DEF_TEST(sk_sp, reporter) { +struct EffectImpl : public Effect { + static sk_sp Create() { + return sk_sp(new EffectImpl); + } + int fValue; +}; +static sk_sp make_effect() { + auto foo = EffectImpl::Create(); + foo->fValue = 42; + return std::move(foo); +} + +static void reset_counters() { gRefCounter = 0; gUnrefCounter = 0; gNewCounter = 0; gDeleteCounter = 0; +} +DEF_TEST(sk_sp, reporter) { + reset_counters(); Paint paint; REPORTER_ASSERT(reporter, paint.fEffect.get() == nullptr); @@ -167,5 +182,68 @@ DEF_TEST(sk_sp, reporter) { delete paint.get()->method(); check(reporter, 2, 1, 2, 1); + + paint.set(nullptr); + e = nullptr; + paint2.set(nullptr); + check(reporter, 2, 4, 2, 2); + + reset_counters(); + { + // Test convertible sk_sp assignment. + check(reporter, 0, 0, 0, 0); + sk_sp foo(nullptr); + REPORTER_ASSERT(reporter, !foo); + foo = make_effect(); + REPORTER_ASSERT(reporter, foo); + check(reporter, 0, 0, 1, 0); + } + check(reporter, 0, 1, 1, 1); + + // Test passing convertible rvalue into funtion. + reset_counters(); + paint.set(EffectImpl::Create()); + check(reporter, 0, 0, 1, 0); + paint.set(nullptr); + check(reporter, 0, 1, 1, 1); + + reset_counters(); + auto baz = EffectImpl::Create(); + check(reporter, 0, 0, 1, 0); + paint.set(std::move(baz)); + check(reporter, 0, 0, 1, 0); + REPORTER_ASSERT(reporter, !baz); + paint.set(nullptr); + check(reporter, 0, 1, 1, 1); + + reset_counters(); + { + // test comparison operator with convertible type. + sk_sp bar1 = EffectImpl::Create(); + sk_sp bar2(bar1); // convertible copy constructor + check(reporter, 1, 0, 1, 0); + REPORTER_ASSERT(reporter, bar1); + REPORTER_ASSERT(reporter, bar2); + REPORTER_ASSERT(reporter, bar1 == bar2); + REPORTER_ASSERT(reporter, bar2 == bar1); + REPORTER_ASSERT(reporter, !(bar1 != bar2)); + REPORTER_ASSERT(reporter, !(bar2 != bar1)); + sk_sp bar3(nullptr); + bar3 = bar1; // convertible copy assignment + check(reporter, 2, 0, 1, 0); + + } + check(reporter, 2, 3, 1, 1); + + // test passing convertible copy into funtion. + reset_counters(); + baz = EffectImpl::Create(); + check(reporter, 0, 0, 1, 0); + paint.set(baz); + check(reporter, 1, 0, 1, 0); + baz = nullptr; + check(reporter, 1, 1, 1, 0); + paint.set(nullptr); + check(reporter, 1, 2, 1, 1); }