Add rvalue accessors to expected and optional, and update constructors. (#690)

* Add rvalue methods to optional and expected.

* Fix constructors in expected.h.

* Fix sanity checks.

---------

Co-authored-by: John Wellbelove <jwellbelove@users.noreply.github.com>
This commit is contained in:
Michael Morgan 2023-05-20 03:42:36 -07:00 committed by GitHub
parent 52d46ebf62
commit 760ff8bd21
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 225 additions and 112 deletions

View File

@ -113,35 +113,28 @@ namespace etl
}
#endif
#if ETL_CPP11_SUPPORTED
//*******************************************
/// Construct from argument.
/// Construct from an lvalue.
//*******************************************
template <typename TErr = TError, typename = typename etl::enable_if<!etl::is_same<typename etl::remove_cvref<TErr>::type, unexpected>::value &&
!etl::is_same<typename etl::remove_cvref<TErr>::type, etl::in_place_t>::value, int>::type>
constexpr explicit unexpected(TErr&& e)
: error_value(etl::forward<TErr>(e))
{
}
#else
//*******************************************
/// Construct from argument.
//*******************************************
template <typename TErr>
explicit unexpected(const TErr& e, typename etl::enable_if<!etl::is_same<typename etl::remove_cvref<TErr>::type, unexpected>::value &&
!etl::is_same<typename etl::remove_cvref<TErr>::type, etl::in_place_t>::value, int>::type = 0)
ETL_CONSTEXPR explicit unexpected(const TError& e)
: error_value(e)
{
}
#endif
#if ETL_USING_CPP11
//*******************************************
/// Construct from an rvalue.
//*******************************************
ETL_CONSTEXPR explicit unexpected(TError&& e)
: error_value(etl::forward<TError>(e))
{
}
//*******************************************
/// Construct from arguments.
//*******************************************
template <typename... Args >
constexpr explicit unexpected(etl::in_place_t, Args&&... args)
ETL_CONSTEXPR explicit unexpected(etl::in_place_t, Args&&... args)
: error_value(etl::forward<Args>(args)...)
{
}
@ -152,7 +145,7 @@ namespace etl
/// Construct from initializer_list and arguments.
//*******************************************
template <typename U, typename... Args>
constexpr explicit unexpected(etl::in_place_t, std::initializer_list<U> init, Args&&... args)
ETL_CONSTEXPR explicit unexpected(etl::in_place_t, std::initializer_list<U> init, Args&&... args)
: error_value(init, etl::forward<Args>(args)...)
{
}
@ -188,7 +181,7 @@ namespace etl
//*******************************************
/// Get the error.
//*******************************************
TError& error() & noexcept
ETL_CONSTEXPR14 TError& error()& ETL_NOEXCEPT
{
return error_value;
}
@ -196,15 +189,15 @@ namespace etl
//*******************************************
/// Get the error.
//*******************************************
constexpr const TError& error() const& noexcept
ETL_CONSTEXPR14 const TError& error() const& ETL_NOEXCEPT
{
return error_value;
}
//*******************************************
/// Get the error.
//*******************************************
TError&& error() && noexcept
//*******************************************
ETL_CONSTEXPR14 TError&& error()&& ETL_NOEXCEPT
{
return etl::move(error_value);
}
@ -212,7 +205,7 @@ namespace etl
//*******************************************
/// Get the error.
//*******************************************
constexpr TError&& error() const&& noexcept
ETL_CONSTEXPR14 TError&& error() const&& ETL_NOEXCEPT
{
return etl::move(error_value);
}
@ -252,7 +245,7 @@ namespace etl
};
#if ETL_USING_CPP17
inline constexpr unexpect_t unexpect{};
inline ETL_CONSTEXPR unexpect_t unexpect{};
#else
static const unexpect_t unexpect;
#endif
@ -322,8 +315,10 @@ namespace etl
//*******************************************
/// Copy construct from unexpected type.
//*******************************************
template <typename F>
ETL_CONSTEXPR14 explicit expected(const etl::unexpected<F>& ue)
template <typename G>
ETL_CONSTEXPR14
ETL_EXPLICIT_EXPR(!etl::is_convertible_v<const G&, TError>)
expected(const etl::unexpected<G>& ue)
: storage(etl::in_place_index_t<Error_Type>(), ue.error())
{
}
@ -332,8 +327,10 @@ namespace etl
//*******************************************
/// Move construct from unexpected type.
//*******************************************
template <typename F>
ETL_CONSTEXPR14 explicit expected(etl::unexpected<F>&& ue)
template <typename G>
ETL_CONSTEXPR14
ETL_EXPLICIT_EXPR(!etl::is_convertible_v<G, TError>)
expected(etl::unexpected<G>&& ue)
: storage(etl::in_place_index_t<Error_Type>(), etl::move(ue.error()))
{
}
@ -388,7 +385,7 @@ namespace etl
#endif
//*******************************************
///
///
//*******************************************
this_type& operator =(const this_type& other)
{
@ -401,7 +398,7 @@ namespace etl
#if ETL_USING_CPP11
//*******************************************
///
///
//*******************************************
this_type& operator =(this_type&& other)
{
@ -503,7 +500,7 @@ namespace etl
#endif
//*******************************************
///
///
//*******************************************
ETL_NODISCARD
ETL_CONSTEXPR14
@ -513,7 +510,7 @@ namespace etl
}
//*******************************************
///
///
//*******************************************
ETL_NODISCARD
ETL_CONSTEXPR14
@ -524,7 +521,7 @@ namespace etl
#if ETL_USING_CPP11
//*******************************************
///
///
//*******************************************
template <typename U>
ETL_NODISCARD
@ -542,7 +539,7 @@ namespace etl
}
//*******************************************
///
///
//*******************************************
template <typename U>
ETL_NODISCARD
@ -560,7 +557,7 @@ namespace etl
}
//*******************************************
///
///
//*******************************************
ETL_NODISCARD
ETL_CONSTEXPR14
@ -570,7 +567,7 @@ namespace etl
}
//*******************************************
///
///
//*******************************************
ETL_NODISCARD
ETL_CONSTEXPR14
@ -580,17 +577,17 @@ namespace etl
}
//*******************************************
///
///
//*******************************************
ETL_NODISCARD
ETL_CONSTEXPR14
error_type&& error() && ETL_NOEXCEPT
error_type&& error()&& ETL_NOEXCEPT
{
return etl::move(etl::get<Error_Type>(storage));
}
//*******************************************
///
///
//*******************************************
ETL_NODISCARD
ETL_CONSTEXPR14
@ -600,7 +597,7 @@ namespace etl
}
//*******************************************
///
///
//*******************************************
template <typename... Args>
ETL_CONSTEXPR14 value_type& emplace(Args&&... args) ETL_NOEXCEPT
@ -609,7 +606,7 @@ namespace etl
}
//*******************************************
///
///
//*******************************************
template <typename U, typename... Args>
ETL_CONSTEXPR14 value_type& emplace(std::initializer_list<U>& il, Args&&... args) ETL_NOEXCEPT
@ -618,7 +615,7 @@ namespace etl
}
#else
//*******************************************
///
///
//*******************************************
template <typename U>
value_type value_or(const U& default_value) const
@ -634,7 +631,7 @@ namespace etl
}
//*******************************************
///
///
//*******************************************
error_type& error() const
{
@ -643,7 +640,7 @@ namespace etl
#endif
//*******************************************
///
///
//*******************************************
value_type* operator ->()
{
@ -655,7 +652,7 @@ namespace etl
}
//*******************************************
///
///
//*******************************************
const value_type* operator ->() const
{
@ -667,9 +664,9 @@ namespace etl
}
//*******************************************
///
///
//*******************************************
value_type& operator *()
value_type& operator *() ETL_LVALUE_REF_QUALIFIER
{
#if ETL_IS_DEBUG_BUILD
ETL_ASSERT(storage.index() == Value_Type, ETL_ERROR(expected_invalid<TError>));
@ -679,9 +676,9 @@ namespace etl
}
//*******************************************
///
///
//*******************************************
const value_type& operator *() const
const value_type& operator *() const ETL_LVALUE_REF_QUALIFIER
{
#if ETL_IS_DEBUG_BUILD
ETL_ASSERT(storage.index() == Value_Type, ETL_ERROR(expected_invalid<TError>));
@ -690,6 +687,32 @@ namespace etl
return etl::get<value_type>(storage);
}
#if ETL_USING_CPP11
//*******************************************
///
//*******************************************
value_type&& operator *()&&
{
#if ETL_IS_DEBUG_BUILD
ETL_ASSERT(storage.index() == Value_Type, ETL_ERROR(expected_invalid<TError>));
#endif
return etl::move(etl::get<value_type>(storage));
}
//*******************************************
///
//*******************************************
const value_type&& operator *() const&&
{
#if ETL_IS_DEBUG_BUILD
ETL_ASSERT(storage.index() == Value_Type, ETL_ERROR(expected_invalid<TError>));
#endif
return etl::move(etl::get<value_type>(storage));
}
#endif
private:
enum

View File

@ -302,7 +302,7 @@ namespace etl
/// Dereference operator.
//***************************************************************************
ETL_CONSTEXPR20_STL
T& operator *()
T& operator *() ETL_LVALUE_REF_QUALIFIER
{
#if ETL_IS_DEBUG_BUILD && !(ETL_USING_CPP20 && ETL_USING_STL)
ETL_ASSERT(has_value(), ETL_ERROR(optional_invalid));
@ -315,7 +315,7 @@ namespace etl
/// Dereference operator.
//***************************************************************************
ETL_CONSTEXPR20_STL
const T& operator *() const
const T& operator *() const ETL_LVALUE_REF_QUALIFIER
{
#if ETL_IS_DEBUG_BUILD && !(ETL_USING_CPP20 && ETL_USING_STL)
ETL_ASSERT(has_value(), ETL_ERROR(optional_invalid));
@ -324,6 +324,34 @@ namespace etl
return storage.u.value;
}
#if ETL_USING_CPP11
//***************************************************************************
/// Dereference operator.
//***************************************************************************
ETL_CONSTEXPR20_STL
T&& operator *()&&
{
#if ETL_IS_DEBUG_BUILD && !(ETL_USING_CPP20 && ETL_USING_STL)
ETL_ASSERT(has_value(), ETL_ERROR(optional_invalid));
#endif
return etl::move(storage.u.value);
}
//***************************************************************************
/// Dereference operator.
//***************************************************************************
ETL_CONSTEXPR20_STL
const T&& operator *() const&&
{
#if ETL_IS_DEBUG_BUILD && !(ETL_USING_CPP20 && ETL_USING_STL)
ETL_ASSERT(has_value(), ETL_ERROR(optional_invalid));
#endif
return etl::move(storage.u.value);
}
#endif
//***************************************************************************
// Check whether optional contains value
//***************************************************************************
@ -346,7 +374,7 @@ namespace etl
/// Get a reference to the value.
//***************************************************************************
ETL_CONSTEXPR20_STL
T& value()
T& value() ETL_LVALUE_REF_QUALIFIER
{
#if ETL_IS_DEBUG_BUILD
ETL_ASSERT(has_value(), ETL_ERROR(optional_invalid));
@ -359,7 +387,7 @@ namespace etl
/// Get a const reference to the value.
//***************************************************************************
ETL_CONSTEXPR20_STL
const T& value() const
const T& value() const ETL_LVALUE_REF_QUALIFIER
{
#if ETL_IS_DEBUG_BUILD
ETL_ASSERT(has_value(), ETL_ERROR(optional_invalid));
@ -372,11 +400,48 @@ namespace etl
/// Gets the value or a default if not valid.
//***************************************************************************
ETL_CONSTEXPR20_STL
T value_or(T default_value) const
T value_or(const T& default_value) const ETL_LVALUE_REF_QUALIFIER
{
return has_value() ? value() : default_value;
}
#if ETL_USING_CPP11
//***************************************************************************
/// Get an rvalue reference to the value.
//***************************************************************************
ETL_CONSTEXPR20_STL
T&& value()&&
{
#if ETL_IS_DEBUG_BUILD
ETL_ASSERT(has_value(), ETL_ERROR(optional_invalid));
#endif
return etl::move(storage.u.value);
}
//***************************************************************************
/// Get a const rvalue reference to the value.
//***************************************************************************
ETL_CONSTEXPR20_STL
const T&& value() const&&
{
#if ETL_IS_DEBUG_BUILD
ETL_ASSERT(has_value(), ETL_ERROR(optional_invalid));
#endif
return etl::move(storage.u.value);
}
//***************************************************************************
/// Gets the value or a default if not valid.
//***************************************************************************
ETL_CONSTEXPR20_STL
T&& value_or(T&& default_value) const&&
{
return has_value() ? etl::move(value()) : default_value;
}
#endif
//***************************************************************************
/// Swaps this value with another.
//***************************************************************************
@ -739,7 +804,7 @@ namespace etl
//***************************************************************************
/// Dereference operator.
//***************************************************************************
ETL_CONSTEXPR14 T& operator *()
ETL_CONSTEXPR14 T& operator *() ETL_LVALUE_REF_QUALIFIER
{
#if ETL_IS_DEBUG_BUILD
ETL_ASSERT(valid, ETL_ERROR(optional_invalid));
@ -751,7 +816,7 @@ namespace etl
//***************************************************************************
/// Dereference operator.
//***************************************************************************
ETL_CONSTEXPR14 const T& operator *() const
ETL_CONSTEXPR14 const T& operator *() const ETL_LVALUE_REF_QUALIFIER
{
#if ETL_IS_DEBUG_BUILD
ETL_ASSERT(valid, ETL_ERROR(optional_invalid));
@ -760,6 +825,32 @@ namespace etl
return storage;
}
#if ETL_USING_CPP11
//***************************************************************************
/// Dereference operator.
//***************************************************************************
ETL_CONSTEXPR14 T&& operator *()&&
{
#if ETL_IS_DEBUG_BUILD
ETL_ASSERT(valid, ETL_ERROR(optional_invalid));
#endif
return etl::move(storage);
}
//***************************************************************************
/// Dereference operator.
//***************************************************************************
ETL_CONSTEXPR14 const T&& operator *() const&&
{
#if ETL_IS_DEBUG_BUILD
ETL_ASSERT(valid, ETL_ERROR(optional_invalid));
#endif
return etl::move(storage);
}
#endif
//***************************************************************************
/// Bool conversion operator.
//***************************************************************************
@ -779,7 +870,7 @@ namespace etl
//***************************************************************************
/// Get a reference to the value.
//***************************************************************************
ETL_CONSTEXPR14 T& value()
ETL_CONSTEXPR14 T& value() ETL_LVALUE_REF_QUALIFIER
{
#if ETL_IS_DEBUG_BUILD
ETL_ASSERT(valid, ETL_ERROR(optional_invalid));
@ -791,7 +882,7 @@ namespace etl
//***************************************************************************
/// Get a const reference to the value.
//***************************************************************************
ETL_CONSTEXPR14 const T& value() const
ETL_CONSTEXPR14 const T& value() const ETL_LVALUE_REF_QUALIFIER
{
#if ETL_IS_DEBUG_BUILD
ETL_ASSERT(valid, ETL_ERROR(optional_invalid));
@ -803,11 +894,45 @@ namespace etl
//***************************************************************************
/// Gets the value or a default if no valid.
//***************************************************************************
ETL_CONSTEXPR14 T value_or(T default_value) const
ETL_CONSTEXPR14 T value_or(const T& default_value) const ETL_LVALUE_REF_QUALIFIER
{
return valid ? value() : default_value;
}
#if ETL_USING_CPP11
//***************************************************************************
/// Get an rvalue reference to the value.
//***************************************************************************
ETL_CONSTEXPR14 T&& value()&&
{
#if ETL_IS_DEBUG_BUILD
ETL_ASSERT(valid, ETL_ERROR(optional_invalid));
#endif
return etl::move(storage);
}
//***************************************************************************
/// Get a const rvalue reference to the value.
//***************************************************************************
ETL_CONSTEXPR14 const T&& value() const&&
{
#if ETL_IS_DEBUG_BUILD
ETL_ASSERT(valid, ETL_ERROR(optional_invalid));
#endif
return etl::move(storage);
}
//***************************************************************************
/// Gets the value or a default if no valid.
//***************************************************************************
ETL_CONSTEXPR14 T&& value_or(T&& default_value) const&&
{
return valid ? etl::move(value()) : default_value;
}
#endif
//***************************************************************************
/// Swaps this value with another.
//***************************************************************************
@ -947,19 +1072,6 @@ namespace etl
ETL_CONSTEXPR14 bool operator <=(const etl::optional<T>& lhs, const etl::optional<T>& rhs)
{
return !(rhs < lhs);
//if (!lhs.has_value())
//{
// return true;
//}
//else if (!rhs.has_value())
//{
// return false;
//}
//else
//{
// return lhs.value() <= rhs.value();
//}
}
//***************************************************************************
@ -969,19 +1081,6 @@ namespace etl
ETL_CONSTEXPR14 bool operator >(const etl::optional<T>& lhs, const etl::optional<T>& rhs)
{
return (rhs < lhs);
//if (!lhs.has_value())
//{
// return false;
//}
//else if (!rhs.has_value())
//{
// return true;
//}
//else
//{
// return lhs.value() > rhs.value();
//}
}
//***************************************************************************
@ -991,19 +1090,6 @@ namespace etl
ETL_CONSTEXPR14 bool operator >=(const etl::optional<T>& lhs, const etl::optional<T>& rhs)
{
return !(lhs < rhs);
//if (!rhs.has_value())
//{
// return true;
//}
//else if (!lhs.has_value())
//{
// return false;
//}
//else
//{
// return lhs.value() >= rhs.value();
//}
}
//***************************************************************************

View File

@ -70,7 +70,7 @@ SOFTWARE.
//*************************************
// Define debug macros.
#if (defined(_DEBUG) || defined(DEBUG)) && !defined(ETL_DEBUG)
#if (defined(_DEBUG) || defined(DEBUG)) && !defined(ETL_DEBUG)
#define ETL_DEBUG
#endif
@ -246,13 +246,14 @@ SOFTWARE.
#define ETL_MOVE(x) etl::move(x)
#define ETL_ENUM_CLASS(name) enum class name
#define ETL_ENUM_CLASS_TYPE(name, type) enum class name : type
#define ETL_LVALUE_REF_QUALIFIER &
#if ETL_USING_EXCEPTIONS
#define ETL_NOEXCEPT noexcept
#define ETL_NOEXCEPT_EXPR(expression) noexcept(expression)
#define ETL_NOEXCEPT noexcept
#define ETL_NOEXCEPT_EXPR(...) noexcept(__VA_ARGS__)
#else
#define ETL_NOEXCEPT
#define ETL_NOEXCEPT_EXPR(expression)
#define ETL_NOEXCEPT_EXPR(...)
#endif
#else
#define ETL_CONSTEXPR
@ -264,10 +265,11 @@ SOFTWARE.
#define ETL_FINAL
#define ETL_NORETURN
#define ETL_NOEXCEPT
#define ETL_NOEXCEPT_EXPR(expression)
#define ETL_NOEXCEPT_EXPR(...)
#define ETL_MOVE(x) x
#define ETL_ENUM_CLASS(name) enum name
#define ETL_ENUM_CLASS_TYPE(name, type) enum name
#define ETL_LVALUE_REF_QUALIFIER
#endif
//*************************************
@ -303,12 +305,13 @@ SOFTWARE.
//*************************************
// C++20
#if ETL_USING_CPP20 && !defined(ETL_FORCE_NO_ADVANCED_CPP)
#define ETL_LIKELY [[likely]]
#define ETL_UNLIKELY [[unlikely]]
#define ETL_CONSTEXPR20 constexpr
#define ETL_CONSTEVAL consteval
#define ETL_CONSTINIT constinit
#define ETL_NO_UNIQUE_ADDRESS [[no_unique_address]]
#define ETL_LIKELY [[likely]]
#define ETL_UNLIKELY [[unlikely]]
#define ETL_CONSTEXPR20 constexpr
#define ETL_CONSTEVAL consteval
#define ETL_CONSTINIT constinit
#define ETL_NO_UNIQUE_ADDRESS [[no_unique_address]]
#define ETL_EXPLICIT_EXPR(...) explicit(__VA_ARGS__)
#else
#define ETL_LIKELY
#define ETL_UNLIKELY
@ -316,6 +319,7 @@ SOFTWARE.
#define ETL_CONSTEVAL
#define ETL_CONSTINIT
#define ETL_NO_UNIQUE_ADDRESS
#define ETL_EXPLICIT_EXPR(...) explicit
#endif
#if ETL_USING_CPP20 && ETL_USING_STL
@ -443,7 +447,7 @@ namespace etl
static ETL_CONSTANT bool using_generic_compiler = (ETL_USING_GENERIC_COMPILER == 1);
static ETL_CONSTANT bool using_legacy_bitset = (ETL_USING_LEGACY_BITSET == 1);
static ETL_CONSTANT bool using_exceptions = (ETL_USING_EXCEPTIONS == 1);
// Has...
static ETL_CONSTANT bool has_initializer_list = (ETL_HAS_INITIALIZER_LIST == 1);
static ETL_CONSTANT bool has_8bit_types = (ETL_USING_8BIT_TYPES == 1);
@ -464,7 +468,7 @@ namespace etl
// Is...
static ETL_CONSTANT bool is_debug_build = (ETL_IS_DEBUG_BUILD == 1);
}
}