sk_sp: Covariant Move Constructor and Move Assignment
Also Covariant Copy Constructor, Copy Assignment, and comparison operators. GOLD_TRYBOT_URL= https://gold.skia.org/search2?unt=true&query=source_type%3Dgm&master=false&issue=1752093002 Review URL: https://codereview.chromium.org/1752093002
This commit is contained in:
parent
c803ef125d
commit
cb6cb3841a
@ -247,6 +247,9 @@ 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>>
|
||||
sk_sp(const sk_sp<U>& 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<T>&& that) : fPtr(that.release()) {}
|
||||
template <typename U,
|
||||
typename = skstd::enable_if_t<skstd::is_convertible<U, T>::value>>
|
||||
sk_sp(sk_sp<U>&& that) : fPtr(that.release()) {}
|
||||
|
||||
/**
|
||||
* Adopt the bare pointer into the newly created sk_sp.
|
||||
@ -268,7 +274,7 @@ public:
|
||||
SkSafeUnref(fPtr);
|
||||
}
|
||||
|
||||
sk_sp<T>& operator=(std::nullptr_t) { this->reset(); }
|
||||
sk_sp<T>& 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 <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;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 <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; }
|
||||
|
||||
bool operator==(const sk_sp<T>& that) const { return this->get() == that.get(); }
|
||||
bool operator!=(const sk_sp<T>& that) const { return this->get() != that.get(); }
|
||||
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(); }
|
||||
|
||||
explicit operator bool() const { return this->get() != nullptr; }
|
||||
|
||||
|
@ -134,11 +134,26 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
DEF_TEST(sk_sp, reporter) {
|
||||
struct EffectImpl : public Effect {
|
||||
static sk_sp<EffectImpl> Create() {
|
||||
return sk_sp<EffectImpl>(new EffectImpl);
|
||||
}
|
||||
int fValue;
|
||||
};
|
||||
static sk_sp<Effect> 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<Effect> 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<EffectImpl> bar1 = EffectImpl::Create();
|
||||
sk_sp<Effect> 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<Effect> 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);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user