Skip to content

Commit

Permalink
Mark not_null constructors as noexcept when underlying type can be mo…
Browse files Browse the repository at this point in the history
…ved with no exception (#1135)

This enables possible optimisations for trivial types. This also avoids a bug
in std::variant::emplace from GNU's libstdc++.

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=106547
  • Loading branch information
mymedia2 authored Oct 18, 2023
1 parent 52212c2 commit e64c97f
Show file tree
Hide file tree
Showing 2 changed files with 15 additions and 3 deletions.
6 changes: 3 additions & 3 deletions include/gsl/pointers
Original file line number Diff line number Diff line change
Expand Up @@ -100,19 +100,19 @@ public:
static_assert(details::is_comparable_to_nullptr<T>::value, "T cannot be compared to nullptr.");

template <typename U, typename = std::enable_if_t<std::is_convertible<U, T>::value>>
constexpr not_null(U&& u) : ptr_(std::forward<U>(u))
constexpr not_null(U&& u) noexcept(std::is_nothrow_move_constructible<T>::value) : ptr_(std::forward<U>(u))
{
Expects(ptr_ != nullptr);
}

template <typename = std::enable_if_t<!std::is_same<std::nullptr_t, T>::value>>
constexpr not_null(T u) : ptr_(std::move(u))
constexpr not_null(T u) noexcept(std::is_nothrow_move_constructible<T>::value) : ptr_(std::move(u))
{
Expects(ptr_ != nullptr);
}

template <typename U, typename = std::enable_if_t<std::is_convertible<U, T>::value>>
constexpr not_null(const not_null<U>& other) : not_null(other.get())
constexpr not_null(const not_null<U>& other) noexcept(std::is_nothrow_move_constructible<T>::value) : not_null(other.get())
{}

not_null(const not_null& other) = default;
Expand Down
12 changes: 12 additions & 0 deletions tests/notnull_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
#include <sstream> // for operator<<, ostringstream, basic_ostream:...
#include <string> // for basic_string, operator==, string, operator<<
#include <typeinfo> // for type_info
#include <variant> // for variant, monostate, get

#include "deathTestCommon.h"
using namespace gsl;
Expand Down Expand Up @@ -514,6 +515,17 @@ TEST(notnull_tests, TestNotNullConstructorTypeDeduction)
}
#endif
}

TEST(notnull_tests, TestVariantEmplace)
{
int i = 0;
std::variant<std::monostate, not_null<int*>> v;
v.emplace<not_null<int*>>(&i);

EXPECT_FALSE(v.valueless_by_exception());
EXPECT_TRUE(v.index() == 1);
EXPECT_TRUE(std::get<not_null<int*>>(v) == &i);
}
#endif // #if defined(__cplusplus) && (__cplusplus >= 201703L)

TEST(notnull_tests, TestMakeNotNull)
Expand Down

0 comments on commit e64c97f

Please sign in to comment.