From b5dfa99a1f9828fad93942d2c0a4feb41d7a9377 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A1rton=20Sz=C3=A1sz?= Date: Tue, 7 Dec 2021 18:08:45 +0100 Subject: [PATCH] expected: Allow to move-assign from move-only unexpected (#40) Fix concept checks in the assignment operators (thanks @szaszm) --- README.md | 1 + include/nonstd/expected.hpp | 14 ++++++++------ test/expected.t.cpp | 22 ++++++++++++++++++++++ 3 files changed, 31 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 80ea652..b9b6af1 100644 --- a/README.md +++ b/README.md @@ -402,6 +402,7 @@ expected: Allows to move-assign from expected, error expected: Allows to forward-assign from value expected: Allows to copy-assign from unexpected expected: Allows to move-assign from unexpected +expected: Allows to move-assign from move-only unexpected expected: Allows to emplace value expected: Allows to emplace value from initializer_list expected: Allows to be swapped diff --git a/include/nonstd/expected.hpp b/include/nonstd/expected.hpp index d6c7ab1..1effd66 100644 --- a/include/nonstd/expected.hpp +++ b/include/nonstd/expected.hpp @@ -1664,10 +1664,11 @@ class expected return *this; } - template< typename G + template< typename G = E nsel_REQUIRES_T( - std::is_copy_constructible::value // TODO: std::is_nothrow_copy_constructible - && std::is_copy_assignable::value + std::is_constructible::value && + std::is_copy_constructible::value // TODO: std::is_nothrow_copy_constructible + && std::is_copy_assignable::value ) > expected & operator=( nonstd::unexpected_type const & error ) @@ -1676,10 +1677,11 @@ class expected return *this; } - template< typename G + template< typename G = E nsel_REQUIRES_T( - std::is_move_constructible::value // TODO: std::is_nothrow_move_constructible - && std::is_move_assignable::value + std::is_constructible::value && + std::is_move_constructible::value // TODO: std::is_nothrow_move_constructible + && std::is_move_assignable::value ) > expected & operator=( nonstd::unexpected_type && error ) diff --git a/test/expected.t.cpp b/test/expected.t.cpp index b2ddaa2..5253041 100644 --- a/test/expected.t.cpp +++ b/test/expected.t.cpp @@ -29,6 +29,18 @@ using namespace nonstd; struct Implicit { int x; Implicit(int v) : x(v) {} }; struct Explicit { int x; explicit Explicit(int v) : x(v) {} }; +struct MoveOnly { + int x; + explicit MoveOnly(int x) :x{x} {} + MoveOnly(const MoveOnly&) = delete; + MoveOnly(MoveOnly&& other) noexcept :x{other.x} {} + MoveOnly& operator=(const MoveOnly&) = delete; + MoveOnly& operator=(MoveOnly&& other) noexcept { + if (&other == this) return *this; + x = other.x; + return *this; + } +}; bool operator==( Implicit a, Implicit b ) { return a.x == b.x; } bool operator==( Explicit a, Explicit b ) { return a.x == b.x; } @@ -902,6 +914,16 @@ CASE( "expected: Allows to move-assign from unexpected" ) EXPECT( e.error() == 7 ); } +CASE( "expected: Allows to move-assign from move-only unexpected" ) +{ + expected e; + unexpected_type u{7}; + + e = std::move( u ); + + EXPECT( e.error() == 7 ); +} + CASE( "expected: Allows to emplace value" ) { expected a;