From e64c97fc2cfc11992098bb38eda932de275e3f4d Mon Sep 17 00:00:00 2001 From: Nicholas Guriev Date: Thu, 19 Oct 2023 01:15:26 +0300 Subject: [PATCH] Mark not_null constructors as noexcept when underlying type can be moved 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 --- include/gsl/pointers | 6 +++--- tests/notnull_tests.cpp | 12 ++++++++++++ 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/include/gsl/pointers b/include/gsl/pointers index 8cd4eb50..611e3641 100644 --- a/include/gsl/pointers +++ b/include/gsl/pointers @@ -100,19 +100,19 @@ public: static_assert(details::is_comparable_to_nullptr::value, "T cannot be compared to nullptr."); template ::value>> - constexpr not_null(U&& u) : ptr_(std::forward(u)) + constexpr not_null(U&& u) noexcept(std::is_nothrow_move_constructible::value) : ptr_(std::forward(u)) { Expects(ptr_ != nullptr); } template ::value>> - constexpr not_null(T u) : ptr_(std::move(u)) + constexpr not_null(T u) noexcept(std::is_nothrow_move_constructible::value) : ptr_(std::move(u)) { Expects(ptr_ != nullptr); } template ::value>> - constexpr not_null(const not_null& other) : not_null(other.get()) + constexpr not_null(const not_null& other) noexcept(std::is_nothrow_move_constructible::value) : not_null(other.get()) {} not_null(const not_null& other) = default; diff --git a/tests/notnull_tests.cpp b/tests/notnull_tests.cpp index 4c317d9c..df8e5a9a 100644 --- a/tests/notnull_tests.cpp +++ b/tests/notnull_tests.cpp @@ -24,6 +24,7 @@ #include // for operator<<, ostringstream, basic_ostream:... #include // for basic_string, operator==, string, operator<< #include // for type_info +#include // for variant, monostate, get #include "deathTestCommon.h" using namespace gsl; @@ -514,6 +515,17 @@ TEST(notnull_tests, TestNotNullConstructorTypeDeduction) } #endif } + +TEST(notnull_tests, TestVariantEmplace) +{ + int i = 0; + std::variant> v; + v.emplace>(&i); + + EXPECT_FALSE(v.valueless_by_exception()); + EXPECT_TRUE(v.index() == 1); + EXPECT_TRUE(std::get>(v) == &i); +} #endif // #if defined(__cplusplus) && (__cplusplus >= 201703L) TEST(notnull_tests, TestMakeNotNull)