Skip to content

Commit

Permalink
not_null no longer requires a copyable pointer type
Browse files Browse the repository at this point in the history
allows support of supporting std::unique_ptr
based on @xaxxon's work

fixes #89
fixes #550
fixes #651
  • Loading branch information
ericLemanissier committed May 2, 2018
1 parent d6b26b3 commit bdf1bcc
Show file tree
Hide file tree
Showing 2 changed files with 53 additions and 3 deletions.
6 changes: 3 additions & 3 deletions include/gsl/pointers
Expand Up @@ -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
Expand Down
50 changes: 50 additions & 0 deletions tests/notnull_tests.cpp
Expand Up @@ -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;
};
Expand Down Expand Up @@ -329,3 +330,52 @@ TEST_CASE("TestNotNullCustomPtrComparison")
}

static_assert(std::is_nothrow_move_constructible<not_null<void *>>::value, "not_null must be no-throw move constructible");

struct UniquePointerTestStruct {
int i = 0;
};

TEST_CASE("TestNotNullUniquePtrComparison") {

{
using NotNull1 = not_null<std::unique_ptr<int>>;

// values are the same
CHECK((*NotNull1(std::make_unique<int>(42)) == *NotNull1(std::make_unique<int>(42))));
}
{
using NotNull1 = not_null<std::unique_ptr<UniquePointerTestStruct>>;

// values are the same
CHECK((NotNull1(std::make_unique<UniquePointerTestStruct>())->i == NotNull1(std::make_unique<UniquePointerTestStruct>())->i));
}
}


template<typename T>
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<UncopyableUnmovablePointerLikeType<int>> fixed_in_place(&i);
CHECK(*fixed_in_place == 5);
}

0 comments on commit bdf1bcc

Please sign in to comment.