diff --git a/include/gsl/pointers b/include/gsl/pointers index ad15ce303..dc30166ee 100644 --- a/include/gsl/pointers +++ b/include/gsl/pointers @@ -86,14 +86,14 @@ public: not_null(const not_null& other) = default; not_null& operator=(const not_null& other) = default; - constexpr T get() const + constexpr T const & get() const { Ensures(ptr_ != nullptr); return ptr_; } - constexpr operator T() const { return get(); } - constexpr T operator->() const { return get(); } + constexpr operator T const & () const { return get(); } + constexpr T const & operator->() const { return get(); } constexpr decltype(auto) operator*() const { return *get(); } // prevents compilation when someone attempts to assign a null pointer constant diff --git a/tests/notnull_tests.cpp b/tests/notnull_tests.cpp index fa99bb78f..c2a4988c6 100644 --- a/tests/notnull_tests.cpp +++ b/tests/notnull_tests.cpp @@ -56,6 +56,7 @@ struct CustomPtr { CustomPtr(T* p) : p_(p) {} operator T*() { return p_; } + operator T*() const { return p_; } bool operator!=(std::nullptr_t) const { return p_ != nullptr; } T* p_ = nullptr; }; @@ -329,3 +330,52 @@ TEST_CASE("TestNotNullCustomPtrComparison") } static_assert(std::is_nothrow_move_constructible>::value, "not_null must be no-throw move constructible"); + +struct UniquePointerTestStruct { + int i = 0; +}; + +TEST_CASE("TestNotNullUniquePtrComparison") { + + { + using NotNull1 = not_null>; + + // values are the same + CHECK((*NotNull1(std::make_unique(42)) == *NotNull1(std::make_unique(42)))); + } + { + using NotNull1 = not_null>; + + // values are the same + CHECK((NotNull1(std::make_unique())->i == NotNull1(std::make_unique())->i)); + } +} + + +template +struct UncopyableUnmovablePointerLikeType { +private: + T * t; + +public: + UncopyableUnmovablePointerLikeType(T * pointer) : t(pointer) {} + UncopyableUnmovablePointerLikeType& operator=(std::nullptr_t) + { + t = nullptr; + return *this; + }; + UncopyableUnmovablePointerLikeType(const UncopyableUnmovablePointerLikeType&) = delete; + UncopyableUnmovablePointerLikeType(UncopyableUnmovablePointerLikeType &&) = delete; + + operator T*() { return t; } + operator T*() const { return t; } +}; + + +// this test case makes sure not_null works on move-only types like std::unique_ptr as well as verifying +// that no copy penalty is being paid for types with expensive copy constructors like std::shared_ptr +TEST_CASE("ConfirmCopyableAndMoveablePointerTypeNotRequired") { + int i = 5; + gsl::not_null> fixed_in_place(&i); + CHECK(*fixed_in_place == 5); +} \ No newline at end of file