mirror of
https://github.com/microsoft/GSL.git
synced 2024-11-03 17:56:43 -05:00
not_null no longer requires a copyable pointer type, now supporting std::unique_ptr
This commit is contained in:
parent
7757e7ec9f
commit
63cf89f340
@ -68,10 +68,9 @@ using owner = T;
|
||||
template <class T>
|
||||
class not_null
|
||||
{
|
||||
public:
|
||||
static_assert(std::is_assignable<T&, std::nullptr_t>::value, "T cannot be assigned nullptr.");
|
||||
|
||||
template <typename U, typename = std::enable_if_t<std::is_convertible<U, T>::value>>
|
||||
public:
|
||||
template <typename U, typename = typename std::enable_if<std::is_constructible<T, U>::value>::type>
|
||||
constexpr not_null(U&& u) : ptr_(std::forward<U>(u))
|
||||
{
|
||||
Expects(ptr_ != nullptr);
|
||||
@ -86,7 +85,8 @@ 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
|
||||
{
|
||||
/*
|
||||
not_null constructors and assignment operators always verify ptr_ is
|
||||
@ -97,8 +97,8 @@ public:
|
||||
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
|
||||
|
@ -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,47 @@ 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(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);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user