Skip to content

Commit

Permalink
Merge pull request #901 from leapmotion/nullptroverload
Browse files Browse the repository at this point in the history
Add some operator overload support for comparison to nullptr_t
  • Loading branch information
yeswalrus committed Apr 18, 2016
2 parents 5865e01 + 1c0dff7 commit eb3d0e9
Show file tree
Hide file tree
Showing 2 changed files with 58 additions and 1 deletion.
24 changes: 23 additions & 1 deletion src/autowiring/Autowired.h
Original file line number Diff line number Diff line change
Expand Up @@ -102,18 +102,34 @@ class Autowired:
autowiring::AutowirableSlot<T>(static_cast<autowiring::AutowirableSlot<T>&>(rhs))
{}

Autowired(const std::shared_ptr<CoreContext>& ctxt = CoreContext::CurrentContext()) :
explicit Autowired(const std::shared_ptr<CoreContext>& ctxt = CoreContext::CurrentContext()) :
autowiring::AutowirableSlot<T>(ctxt)
{}

operator const std::shared_ptr<T>&(void) const {
return static_cast<const AnySharedPointerT<T>&>(this->m_ptr).get();
}

template<typename U>
operator std::shared_ptr<U>(void) const {
return static_cast<const AnySharedPointerT<T>&>(this->m_ptr).get();
}

operator std::weak_ptr<T>(void) const {
return this->operator const std::shared_ptr<T>&();
}

bool operator==(std::nullptr_t) const { return !this->m_ptr; }
bool operator!=(std::nullptr_t) const { return !!this->m_ptr; }
bool operator==(const std::shared_ptr<T>& rhs) const { return this->m_ptr == rhs; }
bool operator!=(const std::shared_ptr<T>& rhs) const { return this->m_ptr != rhs; }

template<typename U>
bool operator==(const std::shared_ptr<U>& rhs) const { return this->m_ptr == rhs; }

template<typename U>
bool operator!=(const std::shared_ptr<U>& rhs) const { return this->m_ptr != rhs; }

operator T*(void) const {
return this->operator const std::shared_ptr<T>&().get();
}
Expand Down Expand Up @@ -185,6 +201,12 @@ class Autowired:
}
};

template<typename T, typename U>
bool operator==(const std::shared_ptr<T>& lhs, const Autowired<U>& rhs) { return rhs == lhs; }

template<typename T, typename U>
bool operator!=(const std::shared_ptr<T>& lhs, const Autowired<U>& rhs) { return rhs != lhs; }

/// <summary>
/// Autowires the specified dependency, creating a new instance if one does not already exist.
/// </summary>
Expand Down
35 changes: 35 additions & 0 deletions src/autowiring/test/AutowiringTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ TEST_F(AutowiringTest, VerifyAutowiredFast) {
// Verify that AutowiredFast can find this object
AutowiredFast<SimpleObject> sobj;
ASSERT_TRUE(sobj.IsAutowired()) << "Failed to autowire an object which was just injected into a context";
ASSERT_NE(sobj, nullptr);
}

TEST_F(AutowiringTest, VerifyAutowiredFastNontrivial) {
Expand All @@ -35,10 +36,12 @@ TEST_F(AutowiringTest, VerifyAutowiredFastNontrivial) {
// Now we add the object
AutoRequired<SimpleReceiver>();
ASSERT_FALSE(ciEmpty.IsAutowired()) << "An AutowiredFast field was incorrectly satisfied post-hoc";
ASSERT_EQ(nullptr, ciEmpty);

// Verify that AutowiredFast can find this object from its interface
AutowiredFast<CallableInterface> ci;
ASSERT_TRUE(ci.IsAutowired()) << "Failed to autowire an interface advertised by a newly-inserted object";
ASSERT_NE(nullptr, ci);
}

template<int N>
Expand Down Expand Up @@ -118,6 +121,7 @@ TEST_F(AutowiringTest, PostHocTypeAdvertisement) {
Autowired<PrivateBase> pb;

ASSERT_FALSE(pb.IsAutowired()) << "Private base type was present in the context before it was advertised";

ctxt->Add(
std::shared_ptr<PrivateBase>{
dcdt,
Expand Down Expand Up @@ -241,3 +245,34 @@ TEST_F(AutowiringTest, FastNullDereferenceTest) {
ASSERT_STREQ("Attempted to dereference a null AutowiredFast<SimpleObject>", dre.what());
}
}

TEST_F(AutowiringTest, ComparisonOverloadTest) {
Autowired<SimpleObject> sobj;

// These two tests actually resolve to different overloads, so we need to ensure both expressions do get called
ASSERT_EQ(nullptr, sobj);
ASSERT_TRUE(sobj == nullptr);

// The remainder of the test will be on the positive comparison case, so we can inject now
AutoRequired<SimpleObject>{};

// Same here as above
ASSERT_NE(sobj, nullptr);
ASSERT_NE(nullptr, sobj);

// Another test to verify our shared pointer casts all resolve properly
ASSERT_EQ(static_cast<const std::shared_ptr<SimpleObject>&>(sobj), sobj);
ASSERT_EQ(sobj, static_cast<const std::shared_ptr<SimpleObject>&>(sobj));

// We should also be able to handle casted versions of the same
std::shared_ptr<ContextMember> base;
ASSERT_NE(base, sobj);
ASSERT_NE(sobj, base);
base = sobj;
ASSERT_EQ(base, sobj);
ASSERT_EQ(sobj, base);

// Finally we also support primitive pointer comparisons
ASSERT_EQ(sobj.get(), sobj);
ASSERT_EQ(sobj, sobj.get());
}

0 comments on commit eb3d0e9

Please sign in to comment.