EXPECT_UAF(ref->DoThing());
}
+void TestEquality() {
+ zc::owned<C> a(new C());
+ zc::owned<C> b(new C());
+
+ EXPECT(a == a);
+ EXPECT(b == b);
+ EXPECT(a != b);
+
+ zc::ref<C> ra = a.get();
+ zc::ref<C> rb = b.get();
+
+ EXPECT(ra == ra);
+ EXPECT(ra == a.get());
+ EXPECT(rb == rb);
+ EXPECT(rb == b.get());
+
+ EXPECT(rb != ra);
+
+ zc::ref<C> r = a.get();
+ EXPECT(r == ra);
+ EXPECT(r == a.get());
+
+ zc::owned<C> c;
+ zc::owned<C> c2;
+ zc::ref<C> rc = nullptr;
+
+ EXPECT(rc == c.get());
+ EXPECT(c == nullptr);
+ EXPECT(rc == nullptr);
+ EXPECT(a != c);
+ EXPECT(c == c2);
+}
+
+void TestNulls() {
+ zc::owned<C> l;
+ zc::owned<C> r;
+
+ zc::ref<C> rl = l.get();
+ zc::ref<C> rr = r.get();
+
+ r = std::move(l);
+ rl = rr;
+
+ EXPECT(l == nullptr);
+ EXPECT(r == nullptr);
+ EXPECT(rl == nullptr);
+ EXPECT(rr == nullptr);
+}
+
#define TEST_FUNC(fn) { #fn , Test##fn }
int main() {
TEST_FUNC(Reset),
TEST_FUNC(Move),
TEST_FUNC(Ptr),
+ TEST_FUNC(Equality),
+ TEST_FUNC(Nulls),
};
bool passed = true;
OwnedPtrDeleter(OwnedPtrDeleter&& other) : refs_(std::move(other.refs_)) {
}
+ void operator=(const OwnedPtrDeleter& o) {
+ refs_ = o.refs_;
+ }
+
void operator()(T* t) const {
for (auto& ref : refs_) {
ref->MarkDeleted();
template <typename T>
class ref {
public:
- ref() : ptr_(DeletedSentinel()) {}
+ ref() : ptr_(nullptr) {}
+
+ ref(std::nullptr_t) : ref() {}
- explicit ref(owned<T>& o) : ptr_(&o) {
- ptr_->get_deleter().AddRef(this);
+ explicit ref(owned<T>& o) : ptr_(nullptr) {
+ if (o != nullptr) {
+ ptr_ = &o;
+ ptr_->get_deleter().AddRef(this);
+ }
}
- ref(const ref<T>& o) {
- *this = o;
+ ref(const ref<T>& r) {
+ *this = r;
}
ref<T>& operator=(const ref<T>& o) {
ptr_ = o.ptr_;
- if (!IsDeleted()) {
+ if (ptr_ != nullptr && !IsDeleted()) {
ptr_->get_deleter().AddRef(this);
}
return *this;
}
~ref() {
- if (!IsDeleted()) {
+ if (ptr_ != nullptr && !IsDeleted()) {
ptr_->get_deleter().RemoveRef(this);
- MarkDeleted();
}
+ MarkDeleted();
}
T* operator->() const {
return ptr_->operator->();
}
+ bool operator==(const ref<T>& r) const {
+ if (ptr_ == nullptr) {
+ return r.ptr_ == nullptr;
+ } else {
+ return ptr_ == r.ptr_ && *ptr_ == *r.ptr_;
+ }
+ }
+
+ bool operator==(std::nullptr_t) const {
+ return ptr_ == nullptr;
+ }
+
+ bool operator!=(const ref<T>& r) const {
+ return !(*this == r);
+ }
+
protected:
friend class internal::OwnedPtrDeleter<T>;