Improve move semantics in Expected (#4326)

* Improve move semantics in Expected:

This patch unconditionally moves an `Unexpected<U>` value parameter as
long as `U` is not a reference. If `U` is a reference the code should
not compile. An error type that holds a reference is a strange use-case,
and an overload is not provided. If it is required in the future it can
be added.

The `Expected(U r)` overload should take a forwarding ref.

* Replace enable_if with concepts in Expected
This commit is contained in:
Scott Determan
2022-11-28 17:01:54 -05:00
committed by Richard Holland
parent 63f80ea033
commit 9fc1a786dc

View File

@@ -21,7 +21,10 @@
#define RIPPLE_BASICS_EXPECTED_H_INCLUDED
#include <ripple/basics/contract.h>
#include <boost/outcome.hpp>
#include <concepts>
#include <stdexcept>
#include <type_traits>
@@ -132,17 +135,16 @@ class [[nodiscard]] Expected
using Base = boost::outcome_v2::result<T, E, detail::throw_policy>;
public:
template <
typename U,
typename = std::enable_if_t<std::is_convertible_v<U, T>>>
constexpr Expected(U r) : Base(T{std::forward<U>(r)})
template <typename U>
requires std::convertible_to<U, T> constexpr Expected(U && r)
: Base(T{std::forward<U>(r)})
{
}
template <
typename U,
typename = std::enable_if_t<std::is_convertible_v<U, E>>>
constexpr Expected(Unexpected<U> e) : Base(E{std::forward<U>(e.value())})
template <typename U>
requires std::convertible_to<U, E> &&
(!std::is_reference_v<U>)constexpr Expected(Unexpected<U> e)
: Base(E{std::move(e.value())})
{
}
@@ -215,10 +217,10 @@ public:
{
}
template <
typename U,
typename = std::enable_if_t<std::is_convertible_v<U, E>>>
constexpr Expected(Unexpected<U> e) : Base(E{std::forward<U>(e.value())})
template <typename U>
requires std::convertible_to<U, E> &&
(!std::is_reference_v<U>)constexpr Expected(Unexpected<U> e)
: Base(E{std::move(e.value())})
{
}