Skip to content

Commit

Permalink
introduce gsl::swap for swapping gsl::not_null (#1160)
Browse files Browse the repository at this point in the history
fixes: #1129

* create gsl::swap<T>(T&, T&) which wraps std::swap
* specialize gsl::swap<T>(gsl::not_null<T>&, gsl::not_null<T>&)
* add tests
  • Loading branch information
carsonRadtke authored Dec 13, 2024
1 parent 8a0e3d8 commit 2724630
Show file tree
Hide file tree
Showing 5 changed files with 53 additions and 0 deletions.
20 changes: 20 additions & 0 deletions docs/headers.md
Original file line number Diff line number Diff line change
Expand Up @@ -294,6 +294,12 @@ void operator[](std::ptrdiff_t) const = delete;

Array index operator is explicitly deleted. Pointers point to single objects ([I.13: Do not pass an array as a single pointer](http://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#Ri-array)), so don't allow treating them as an array.

```cpp
void swap(not_null<T>& other) { std::swap(ptr_, other.ptr_); }
```
Swaps contents with another `gsl::not_null` object.
#### Non-member functions
```cpp
Expand All @@ -303,6 +309,13 @@ auto make_not_null(T&& t) noexcept;

Creates a `gsl::not_null` object, deducing the target type from the type of the argument.

```cpp
template <typename T, typename = std::enable_if_t<std::is_move_assignable<T>::value && std::is_move_constructible<T>::value>>
void swap(not_null<T>& a, not_null<T>& b);
```
Swaps the contents of two `gsl::not_null` objects.
```cpp
template <class T, class U>
auto operator==(const not_null<T>& lhs,
Expand Down Expand Up @@ -858,3 +871,10 @@ constexpr auto at(std::span<T, extent> sp, const index i) -> decltype(sp[sp.size
This overload returns a reference to the `i`s element of the `std::span` `sp`. It [`Expects`](#user-content-H-assert-expects) that the provided index is within the bounds of the array.

For [`gsl::at`](#user-content-H-span_ext-at) for [`gsl::span`](#user-content-H-span-span) see header [`span_ext`](#user-content-H-span_ext).

```cpp
template <class T, std::enable_if_t<std::is_move_assignable<T>::value && std::is_move_constructible<T>::value>>
void swap(T& a, T& b);
```
Swaps the contents of two objects. Exists only to specialize `gsl::swap<T>(gsl::not_null<T>&, gsl::not_null<T>&)`.
8 changes: 8 additions & 0 deletions include/gsl/pointers
Original file line number Diff line number Diff line change
Expand Up @@ -139,10 +139,18 @@ public:
not_null& operator-=(std::ptrdiff_t) = delete;
void operator[](std::ptrdiff_t) const = delete;

void swap(not_null<T>& other) { std::swap(ptr_, other.ptr_); }

private:
T ptr_;
};

template <typename T, typename = std::enable_if_t<std::is_move_assignable<T>::value && std::is_move_constructible<T>::value>>
void swap(not_null<T>& a, not_null<T>& b)
{
a.swap(b);
}

template <class T>
auto make_not_null(T&& t) noexcept
{
Expand Down
3 changes: 3 additions & 0 deletions include/gsl/util
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,9 @@ GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute
return *(cont.begin() + i);
}

template <class T, std::enable_if_t<std::is_move_assignable<T>::value && std::is_move_constructible<T>::value>>
void swap(T& a, T& b) { std::swap(a, b); }

#if defined(__cpp_lib_span) && __cpp_lib_span >= 202002L
template <class T, std::size_t extent = std::dynamic_extent>
constexpr auto at(std::span<T, extent> sp, const index i) -> decltype(sp[sp.size()])
Expand Down
1 change: 1 addition & 0 deletions tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,7 @@ add_executable(gsl_tests
byte_tests.cpp
notnull_tests.cpp
owner_tests.cpp
pointers_tests.cpp
span_compatibility_tests.cpp
span_ext_tests.cpp
span_tests.cpp
Expand Down
21 changes: 21 additions & 0 deletions tests/pointers_tests.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
#include <gtest/gtest.h>

#include <gsl/pointers>

#include <memory>

TEST(pointers_test, swap)
{
// taken from gh-1129:
gsl::not_null<std::unique_ptr<int>> a(std::make_unique<int>(0));
gsl::not_null<std::unique_ptr<int>> b(std::make_unique<int>(1));

EXPECT_TRUE(*a == 0);
EXPECT_TRUE(*b == 1);

gsl::swap(a, b);

EXPECT_TRUE(*a == 1);
EXPECT_TRUE(*b == 0);
}

1 comment on commit 2724630

@beinhaerter
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't there also be code for swapping strict_not_nulls?

Please sign in to comment.