diff --git a/include/cru/common/SelfResolvable.h b/include/cru/common/SelfResolvable.h index 5a609340..c0ca9326 100644 --- a/include/cru/common/SelfResolvable.h +++ b/include/cru/common/SelfResolvable.h @@ -28,8 +28,6 @@ class ObjectResolver { return *this->shared_object_ptr_; } - explicit operator bool() const { return this->IsValid(); } - private: void SetResolvedObject(T* o) { assert(IsValid()); @@ -43,14 +41,14 @@ class ObjectResolver { template class SelfResolvable { public: - SelfResolvable() : resolver_(static_cast(this)) {} + SelfResolvable() : resolver_(CastToSubClass()) {} SelfResolvable(const SelfResolvable&) = delete; SelfResolvable& operator=(const SelfResolvable&) = delete; // Resolvers to old object will resolve to new object. SelfResolvable(SelfResolvable&& other) : resolver_(std::move(other.resolver_)) { - this->resolver_.SetResolvedObject(this); + this->resolver_.SetResolvedObject(CastToSubClass()); } // Old resolvers for this object will resolve to nullptr. @@ -58,7 +56,7 @@ class SelfResolvable { SelfResolvable& operator=(SelfResolvable&& other) { if (this != &other) { this->resolver_ = std::move(other.resolver_); - this->resolver_.SetResolvedObject(this); + this->resolver_.SetResolvedObject(CastToSubClass()); } return *this; } @@ -71,6 +69,9 @@ class SelfResolvable { ObjectResolver CreateResolver() { return resolver_; } + private: + T* CastToSubClass() { return static_cast(this); } + private: ObjectResolver resolver_; }; diff --git a/test/common/CMakeLists.txt b/test/common/CMakeLists.txt index 650e82a9..602af819 100644 --- a/test/common/CMakeLists.txt +++ b/test/common/CMakeLists.txt @@ -1,6 +1,7 @@ add_executable(CruBaseTest HandlerRegistryTest.cpp PropertyTreeTest.cpp + SelfResolvableTest.cpp StringTest.cpp StringToNumberConverterTest.cpp StringUtilTest.cpp diff --git a/test/common/SelfResolvableTest.cpp b/test/common/SelfResolvableTest.cpp new file mode 100644 index 00000000..3664a223 --- /dev/null +++ b/test/common/SelfResolvableTest.cpp @@ -0,0 +1,76 @@ +#include "cru/common/Base.h" +#include "cru/common/SelfResolvable.h" + +#include + +#include + +namespace { +class SelfResolvableTestClass + : public cru::SelfResolvable { + public: + SelfResolvableTestClass() : ptr_(new int(123)) {} + CRU_DELETE_COPY(SelfResolvableTestClass) + CRU_DEFAULT_MOVE(SelfResolvableTestClass) + ~SelfResolvableTestClass() = default; + + private: + std::shared_ptr ptr_; +}; +} // namespace + +TEST_CASE("SelfResolvable resolver should work.", "[self-resolvable]") { + SelfResolvableTestClass test_object; + + auto resolver = test_object.CreateResolver(); + REQUIRE(resolver.Resolve() == &test_object); + + auto resolver_copy = resolver; + REQUIRE(resolver.Resolve() == &test_object); + REQUIRE(resolver.Resolve() == &test_object); + + auto resolver_move = std::move(resolver_copy); + REQUIRE(resolver.Resolve() == &test_object); + REQUIRE(resolver_copy.IsValid() == false); + REQUIRE(resolver_move.Resolve() == &test_object); +} + +TEST_CASE("SelfResolvable object destructed should work.", + "[self-resolvable]") { + SelfResolvableTestClass* test_object = new SelfResolvableTestClass(); + + auto resolver = test_object->CreateResolver(); + auto resolver_copy = resolver; + + delete test_object; + + REQUIRE(resolver.Resolve() == nullptr); + REQUIRE(resolver_copy.Resolve() == nullptr); + + auto resolver_copy2 = resolver_copy; + REQUIRE(resolver_copy2.Resolve() == nullptr); + + auto resolver_move = std::move(resolver_copy); + REQUIRE(resolver_copy.IsValid() == false); + REQUIRE(resolver_move.Resolve() == nullptr); +} + +TEST_CASE("SelfResolvable object moved should work.", "[self-resolvable]") { + SelfResolvableTestClass test_object; + + auto resolver = test_object.CreateResolver(); + auto resolver_copy = resolver; + + SelfResolvableTestClass moved_object = std::move(test_object); + + REQUIRE(resolver.Resolve() == &moved_object); + REQUIRE(resolver_copy.Resolve() == &moved_object); + + auto resolver_copy2 = resolver_copy; + REQUIRE(resolver_copy2.Resolve() == &moved_object); + + auto resolver_move = std::move(resolver_copy); + REQUIRE(resolver_copy.IsValid() == false); + REQUIRE(resolver_move.Resolve() == &moved_object); +} +