mirror of
https://github.com/ETLCPP/etl.git
synced 2026-10-28 18:07:10 +08:00
Allow expected to be constructed from a convertible value or expected (#1587)
This commit is contained in:
parent
d5156f9a1a
commit
d06cd9f303
@ -236,6 +236,72 @@ Since: C++11
|
||||
|
||||
---
|
||||
|
||||
```cpp
|
||||
template <typename U>
|
||||
ETL_CONSTEXPR14 expected(U&& value)
|
||||
```
|
||||
**Description**
|
||||
Construct the value type from a value implicitly convertible to it.
|
||||
Not selected when U is an etl::expected, etl::unexpected, etl::in_place_t, etl::unexpect_t or value_type itself.
|
||||
Since: C++11
|
||||
|
||||
---
|
||||
|
||||
```cpp
|
||||
template <typename U>
|
||||
ETL_CONSTEXPR14 explicit expected(U&& value)
|
||||
```
|
||||
**Description**
|
||||
Construct the value type from a value that is only explicitly convertible to it.
|
||||
Constrained as above.
|
||||
Since: C++11
|
||||
|
||||
---
|
||||
|
||||
```cpp
|
||||
template <typename U, typename G>
|
||||
expected(const etl::expected<U, G>& other)
|
||||
```
|
||||
**Description**
|
||||
Copy construct from an etl::expected<U, G> whose value and error types are both implicitly convertible.
|
||||
Not selected when value_type can be constructed from, or etl::unexpected<error_type> built from, the source etl::expected itself.
|
||||
Since: C++11
|
||||
|
||||
---
|
||||
|
||||
```cpp
|
||||
template <typename U, typename G>
|
||||
explicit expected(const etl::expected<U, G>& other)
|
||||
```
|
||||
**Description**
|
||||
Copy construct from an etl::expected<U, G> whose value or error type is only explicitly convertible.
|
||||
Constrained as above.
|
||||
Since: C++11
|
||||
|
||||
---
|
||||
|
||||
```cpp
|
||||
template <typename U, typename G>
|
||||
expected(etl::expected<U, G>&& other)
|
||||
```
|
||||
**Description**
|
||||
Move construct from an etl::expected<U, G> whose value and error types are both implicitly convertible.
|
||||
Constrained as above.
|
||||
Since: C++11
|
||||
|
||||
---
|
||||
|
||||
```cpp
|
||||
template <typename U, typename G>
|
||||
explicit expected(etl::expected<U, G>&& other)
|
||||
```
|
||||
**Description**
|
||||
Move construct from an etl::expected<U, G> whose value or error type is only explicitly convertible.
|
||||
Constrained as above.
|
||||
Since: C++11
|
||||
|
||||
---
|
||||
|
||||
```cpp
|
||||
ETL_CONSTEXPR14 expected(const expected& other) ETL_NOEXCEPT
|
||||
```
|
||||
@ -353,6 +419,17 @@ Since: C++11
|
||||
|
||||
---
|
||||
|
||||
```cpp
|
||||
template <typename U>
|
||||
expected& operator =(U&& value)
|
||||
```
|
||||
**Description**
|
||||
Assign from a value convertible to value_type.
|
||||
Constrained like the value constructor.
|
||||
Since: C++11
|
||||
|
||||
---
|
||||
|
||||
```cpp
|
||||
expected& operator =(const unexpected_type& error)
|
||||
```
|
||||
|
||||
@ -249,6 +249,92 @@ namespace etl
|
||||
static const unexpect_t unexpect;
|
||||
#endif
|
||||
|
||||
#if ETL_USING_CPP11
|
||||
namespace private_expected
|
||||
{
|
||||
//*****************************************************************************
|
||||
// Detects etl::unexpected, which the value constructors must not accept as a value.
|
||||
//*****************************************************************************
|
||||
template <typename T>
|
||||
struct is_unexpected : etl::false_type
|
||||
{
|
||||
};
|
||||
|
||||
template <typename TError>
|
||||
struct is_unexpected<etl::unexpected<TError> > : etl::true_type
|
||||
{
|
||||
};
|
||||
|
||||
//*****************************************************************************
|
||||
// True when TValue can be built from the source expected, which must be wrapped rather than unwrapped.
|
||||
//*****************************************************************************
|
||||
template <typename TValue, typename U, typename G>
|
||||
struct constructible_from_expected
|
||||
: etl::integral_constant<
|
||||
bool, etl::is_constructible<TValue, etl::expected<U, G>&>::value || etl::is_constructible<TValue, etl::expected<U, G> >::value
|
||||
|| etl::is_constructible<TValue, const etl::expected<U, G>&>::value
|
||||
|| etl::is_constructible<TValue, const etl::expected<U, G> >::value || etl::is_convertible<etl::expected<U, G>&, TValue>::value
|
||||
|| etl::is_convertible<etl::expected<U, G>&&, TValue>::value || etl::is_convertible<const etl::expected<U, G>&, TValue>::value
|
||||
|| etl::is_convertible<const etl::expected<U, G>&&, TValue>::value>
|
||||
{
|
||||
};
|
||||
|
||||
//*****************************************************************************
|
||||
// True when TError can be built from the source expected, which must be wrapped rather than unwrapped.
|
||||
//*****************************************************************************
|
||||
template <typename TError, typename U, typename G>
|
||||
struct unexpected_constructible_from_expected
|
||||
: etl::integral_constant<bool, etl::is_constructible<etl::unexpected<TError>, etl::expected<U, G>&>::value
|
||||
|| etl::is_constructible<etl::unexpected<TError>, etl::expected<U, G> >::value
|
||||
|| etl::is_constructible<etl::unexpected<TError>, const etl::expected<U, G>&>::value
|
||||
|| etl::is_constructible<etl::unexpected<TError>, const etl::expected<U, G> >::value>
|
||||
{
|
||||
};
|
||||
|
||||
//*****************************************************************************
|
||||
// Constraints shared by the implicit and explicit value constructors.
|
||||
//*****************************************************************************
|
||||
template <typename TValue, typename TError, typename U>
|
||||
struct is_value_constructor_candidate
|
||||
: etl::integral_constant<bool, !etl::is_same<typename etl::decay<U>::type, etl::expected<TValue, TError> >::value
|
||||
&& !etl::is_same<typename etl::decay<U>::type, TValue>::value
|
||||
&& !etl::is_same<typename etl::decay<U>::type, etl::in_place_t>::value
|
||||
&& !etl::is_same<typename etl::decay<U>::type, etl::unexpect_t>::value
|
||||
&& !is_unexpected<typename etl::decay<U>::type>::value && etl::is_constructible<TValue, U&&>::value>
|
||||
{
|
||||
};
|
||||
|
||||
//*****************************************************************************
|
||||
// Constraints on the source expected that hold whatever its value category.
|
||||
//*****************************************************************************
|
||||
template <typename TValue, typename TError, typename U, typename G>
|
||||
struct is_expected_conversion_allowed
|
||||
: etl::integral_constant<bool, !etl::is_same<etl::expected<U, G>, etl::expected<TValue, TError> >::value
|
||||
&& !constructible_from_expected<TValue, U, G>::value
|
||||
&& !unexpected_constructible_from_expected<TError, U, G>::value>
|
||||
{
|
||||
};
|
||||
|
||||
//*****************************************************************************
|
||||
// UArgument and GArgument are the source members as the constructor receives them.
|
||||
//*****************************************************************************
|
||||
template <typename TValue, typename TError, typename UArgument, typename GArgument>
|
||||
struct is_expected_conversion_constructible
|
||||
: etl::integral_constant<bool, etl::is_constructible<TValue, UArgument>::value && etl::is_constructible<TError, GArgument>::value>
|
||||
{
|
||||
};
|
||||
|
||||
//*****************************************************************************
|
||||
// A converting constructor is implicit only when both the value and the error convert implicitly.
|
||||
//*****************************************************************************
|
||||
template <typename TValue, typename TError, typename UArgument, typename GArgument>
|
||||
struct is_expected_conversion_implicit
|
||||
: etl::integral_constant<bool, etl::is_convertible<UArgument, TValue>::value && etl::is_convertible<GArgument, TError>::value>
|
||||
{
|
||||
};
|
||||
} // namespace private_expected
|
||||
#endif
|
||||
|
||||
//*****************************************************************************
|
||||
/// Expected type.
|
||||
//*****************************************************************************
|
||||
@ -293,6 +379,114 @@ namespace etl
|
||||
}
|
||||
#endif
|
||||
|
||||
#if ETL_USING_CPP11
|
||||
//*******************************************
|
||||
/// Constructor from a value convertible to value_type.
|
||||
//*******************************************
|
||||
template <typename U,
|
||||
typename etl::enable_if<
|
||||
private_expected::is_value_constructor_candidate<TValue, TError, U>::value && etl::is_convertible<U&&, TValue>::value, int>::type = 0>
|
||||
ETL_CONSTEXPR14 expected(U&& value_)
|
||||
: storage(etl::in_place_index_t<Value_Type>(), etl::forward<U>(value_))
|
||||
{
|
||||
}
|
||||
|
||||
//*******************************************
|
||||
/// Constructor from a value explicitly convertible to value_type.
|
||||
//*******************************************
|
||||
template <typename U, typename etl::enable_if<private_expected::is_value_constructor_candidate<TValue, TError, U>::value
|
||||
&& !etl::is_convertible<U&&, TValue>::value,
|
||||
int>::type = 0>
|
||||
ETL_CONSTEXPR14 explicit expected(U&& value_)
|
||||
: storage(etl::in_place_index_t<Value_Type>(), etl::forward<U>(value_))
|
||||
{
|
||||
}
|
||||
|
||||
//*******************************************
|
||||
/// Copy constructor from an expected with convertible value and error types.
|
||||
//*******************************************
|
||||
template <typename U, typename G,
|
||||
typename etl::enable_if<private_expected::is_expected_conversion_allowed<TValue, TError, U, G>::value
|
||||
&& private_expected::is_expected_conversion_constructible<TValue, TError, const U&, const G&>::value
|
||||
&& private_expected::is_expected_conversion_implicit<TValue, TError, const U&, const G&>::value,
|
||||
int>::type = 0>
|
||||
expected(const etl::expected<U, G>& other)
|
||||
: storage(private_variant::valueless_t())
|
||||
{
|
||||
if (other.has_value())
|
||||
{
|
||||
storage.template emplace<Value_Type>(other.value());
|
||||
}
|
||||
else
|
||||
{
|
||||
storage.template emplace<Error_Type>(other.error());
|
||||
}
|
||||
}
|
||||
|
||||
//*******************************************
|
||||
/// Copy constructor from an expected with explicitly convertible value or error types.
|
||||
//*******************************************
|
||||
template <typename U, typename G,
|
||||
typename etl::enable_if<private_expected::is_expected_conversion_allowed<TValue, TError, U, G>::value
|
||||
&& private_expected::is_expected_conversion_constructible<TValue, TError, const U&, const G&>::value
|
||||
&& !private_expected::is_expected_conversion_implicit<TValue, TError, const U&, const G&>::value,
|
||||
int>::type = 0>
|
||||
explicit expected(const etl::expected<U, G>& other)
|
||||
: storage(private_variant::valueless_t())
|
||||
{
|
||||
if (other.has_value())
|
||||
{
|
||||
storage.template emplace<Value_Type>(other.value());
|
||||
}
|
||||
else
|
||||
{
|
||||
storage.template emplace<Error_Type>(other.error());
|
||||
}
|
||||
}
|
||||
|
||||
//*******************************************
|
||||
/// Move constructor from an expected with convertible value and error types.
|
||||
//*******************************************
|
||||
template <typename U, typename G,
|
||||
typename etl::enable_if<private_expected::is_expected_conversion_allowed<TValue, TError, U, G>::value
|
||||
&& private_expected::is_expected_conversion_constructible<TValue, TError, U&&, G&&>::value
|
||||
&& private_expected::is_expected_conversion_implicit<TValue, TError, U&&, G&&>::value,
|
||||
int>::type = 0>
|
||||
expected(etl::expected<U, G>&& other)
|
||||
: storage(private_variant::valueless_t())
|
||||
{
|
||||
if (other.has_value())
|
||||
{
|
||||
storage.template emplace<Value_Type>(etl::move(other.value()));
|
||||
}
|
||||
else
|
||||
{
|
||||
storage.template emplace<Error_Type>(etl::move(other.error()));
|
||||
}
|
||||
}
|
||||
|
||||
//*******************************************
|
||||
/// Move constructor from an expected with explicitly convertible value or error types.
|
||||
//*******************************************
|
||||
template <typename U, typename G,
|
||||
typename etl::enable_if<private_expected::is_expected_conversion_allowed<TValue, TError, U, G>::value
|
||||
&& private_expected::is_expected_conversion_constructible<TValue, TError, U&&, G&&>::value
|
||||
&& !private_expected::is_expected_conversion_implicit<TValue, TError, U&&, G&&>::value,
|
||||
int>::type = 0>
|
||||
explicit expected(etl::expected<U, G>&& other)
|
||||
: storage(private_variant::valueless_t())
|
||||
{
|
||||
if (other.has_value())
|
||||
{
|
||||
storage.template emplace<Value_Type>(etl::move(other.value()));
|
||||
}
|
||||
else
|
||||
{
|
||||
storage.template emplace<Error_Type>(etl::move(other.error()));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
//*******************************************
|
||||
/// Copy constructor
|
||||
//*******************************************
|
||||
@ -451,6 +645,17 @@ namespace etl
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
//*******************************************
|
||||
/// Assign from a value convertible to value_type.
|
||||
//*******************************************
|
||||
template <typename U, typename etl::enable_if<private_expected::is_value_constructor_candidate<TValue, TError, U>::value, int>::type = 0>
|
||||
expected& operator=(U&& value)
|
||||
{
|
||||
storage.template emplace<Value_Type>(etl::forward<U>(value));
|
||||
|
||||
return *this;
|
||||
}
|
||||
#endif
|
||||
|
||||
//*******************************************
|
||||
|
||||
@ -69,6 +69,14 @@ namespace etl
|
||||
{
|
||||
namespace private_variant
|
||||
{
|
||||
//*******************************************
|
||||
/// Tag for constructing a variant with no alternative.
|
||||
//*******************************************
|
||||
struct valueless_t
|
||||
{
|
||||
explicit ETL_CONSTEXPR valueless_t() {}
|
||||
};
|
||||
|
||||
//*******************************************
|
||||
/// Switch-based dispatch for destroy/copy/move.
|
||||
/// Replaces the per-instance function pointer with
|
||||
@ -1034,6 +1042,16 @@ namespace etl
|
||||
}
|
||||
#include "diagnostic_pop.h"
|
||||
|
||||
//***************************************************************************
|
||||
/// Construct with no alternative.
|
||||
/// The caller is expected to emplace one; until it does the variant is valueless.
|
||||
/// Lets a caller choose the alternative at run time without a temporary variant.
|
||||
//***************************************************************************
|
||||
ETL_CONSTEXPR14 explicit variant(private_variant::valueless_t) ETL_NOEXCEPT
|
||||
: base_type()
|
||||
{
|
||||
}
|
||||
|
||||
//***************************************************************************
|
||||
/// Construct from arguments.
|
||||
//***************************************************************************
|
||||
|
||||
@ -120,6 +120,147 @@ namespace
|
||||
std::string e;
|
||||
};
|
||||
|
||||
struct ExplicitValue
|
||||
{
|
||||
std::string v;
|
||||
|
||||
ExplicitValue() {}
|
||||
|
||||
explicit ExplicitValue(const std::string& v_)
|
||||
: v(v_)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
struct ExplicitError
|
||||
{
|
||||
std::string e;
|
||||
|
||||
ExplicitError() = default;
|
||||
|
||||
explicit ExplicitError(const std::string& e_)
|
||||
: e(e_)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
struct MoveOnlyValue
|
||||
{
|
||||
MoveOnlyValue()
|
||||
: v(0)
|
||||
{
|
||||
}
|
||||
|
||||
explicit MoveOnlyValue(int v_)
|
||||
: v(v_)
|
||||
{
|
||||
}
|
||||
|
||||
MoveOnlyValue(MoveOnlyValue&&) = default;
|
||||
MoveOnlyValue& operator=(MoveOnlyValue&&) = default;
|
||||
|
||||
MoveOnlyValue(const MoveOnlyValue&) = delete;
|
||||
MoveOnlyValue& operator=(const MoveOnlyValue&) = delete;
|
||||
|
||||
int v;
|
||||
};
|
||||
|
||||
struct FromMoveOnlyValue
|
||||
{
|
||||
FromMoveOnlyValue()
|
||||
: v(0)
|
||||
{
|
||||
}
|
||||
|
||||
FromMoveOnlyValue(MoveOnlyValue&& other)
|
||||
: v(other.v)
|
||||
{
|
||||
}
|
||||
|
||||
int v;
|
||||
};
|
||||
|
||||
struct NoMoveValue
|
||||
{
|
||||
explicit NoMoveValue(int v_)
|
||||
: v(v_)
|
||||
{
|
||||
}
|
||||
|
||||
NoMoveValue(const NoMoveValue&) = default;
|
||||
NoMoveValue(NoMoveValue&&) = delete;
|
||||
|
||||
int v;
|
||||
};
|
||||
|
||||
struct FromInt
|
||||
{
|
||||
FromInt()
|
||||
: v(0)
|
||||
{
|
||||
}
|
||||
|
||||
FromInt(int v_)
|
||||
: v(v_)
|
||||
{
|
||||
}
|
||||
|
||||
int v;
|
||||
};
|
||||
|
||||
struct ErrorFromExpected
|
||||
{
|
||||
ErrorFromExpected() {}
|
||||
|
||||
ErrorFromExpected(int) {}
|
||||
|
||||
ErrorFromExpected(const etl::expected<int, int>&) {}
|
||||
};
|
||||
|
||||
struct ImmobileValue
|
||||
{
|
||||
static int destructions;
|
||||
|
||||
explicit ImmobileValue(int v_)
|
||||
: v(v_)
|
||||
{
|
||||
}
|
||||
|
||||
ImmobileValue(const ImmobileValue&) = delete;
|
||||
ImmobileValue(ImmobileValue&&) = delete;
|
||||
|
||||
~ImmobileValue()
|
||||
{
|
||||
++destructions;
|
||||
}
|
||||
|
||||
int v;
|
||||
};
|
||||
|
||||
int ImmobileValue::destructions = 0;
|
||||
|
||||
struct ImmobileError
|
||||
{
|
||||
static int destructions;
|
||||
|
||||
ImmobileError(int e_)
|
||||
: e(e_)
|
||||
{
|
||||
}
|
||||
|
||||
ImmobileError(const ImmobileError&) = delete;
|
||||
ImmobileError(ImmobileError&&) = delete;
|
||||
|
||||
~ImmobileError()
|
||||
{
|
||||
++destructions;
|
||||
}
|
||||
|
||||
int e;
|
||||
};
|
||||
|
||||
int ImmobileError::destructions = 0;
|
||||
|
||||
using Expected = etl::expected<Value, Error>;
|
||||
using ExpectedV = etl::expected<void, Error>;
|
||||
using ExpectedM = etl::expected<ValueM, ErrorM>;
|
||||
@ -1651,5 +1792,196 @@ namespace
|
||||
CHECK_FALSE(result.has_value());
|
||||
CHECK_EQUAL("original_transformed", result.error().e);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_constructor_from_value_convertible_to_value_type)
|
||||
{
|
||||
const Expected result = std::string("converted");
|
||||
|
||||
CHECK_TRUE(result.has_value());
|
||||
CHECK_EQUAL("converted", result.value().v);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_constructor_from_expected_with_convertible_types)
|
||||
{
|
||||
const etl::expected<std::string, std::string> source(std::string("converted"));
|
||||
|
||||
const Expected result(source);
|
||||
|
||||
CHECK_TRUE(result.has_value());
|
||||
CHECK_EQUAL("converted", result.value().v);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_constructor_from_expected_with_convertible_types_carries_error)
|
||||
{
|
||||
const etl::expected<std::string, std::string> source(etl::unexpected<std::string>(std::string("failed")));
|
||||
|
||||
const Expected result(source);
|
||||
|
||||
CHECK_FALSE(result.has_value());
|
||||
CHECK_EQUAL("failed", result.error().e);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_value_type_constructible_from_expected_is_not_unwrapped)
|
||||
{
|
||||
struct WrapsExpected
|
||||
{
|
||||
WrapsExpected()
|
||||
: wrapped(false)
|
||||
{
|
||||
}
|
||||
|
||||
WrapsExpected(const etl::expected<int, Error>&)
|
||||
: wrapped(true)
|
||||
{
|
||||
}
|
||||
|
||||
explicit WrapsExpected(int)
|
||||
: wrapped(false)
|
||||
{
|
||||
}
|
||||
|
||||
bool wrapped;
|
||||
};
|
||||
|
||||
const etl::expected<int, Error> source(7);
|
||||
|
||||
const etl::expected<WrapsExpected, Error> result(source);
|
||||
|
||||
CHECK_TRUE(result.has_value());
|
||||
CHECK_TRUE(result.value().wrapped);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_explicit_value_conversion_is_not_implicit)
|
||||
{
|
||||
using ExplicitExpected = etl::expected<ExplicitValue, Error>;
|
||||
|
||||
CHECK_TRUE((etl::is_constructible<ExplicitExpected, std::string>::value));
|
||||
CHECK_FALSE((etl::is_convertible<std::string, ExplicitExpected>::value));
|
||||
|
||||
CHECK_TRUE((etl::is_convertible<std::string, Expected>::value));
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_explicit_value_conversion_is_available_by_direct_initialisation)
|
||||
{
|
||||
const etl::expected<ExplicitValue, Error> result(std::string("converted"));
|
||||
|
||||
CHECK_TRUE(result.has_value());
|
||||
CHECK_EQUAL("converted", result.value().v);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_explicit_error_conversion_is_not_implicit)
|
||||
{
|
||||
using Source = etl::expected<std::string, std::string>;
|
||||
using ExplicitExpected = etl::expected<Value, ExplicitError>;
|
||||
|
||||
CHECK_TRUE((etl::is_constructible<ExplicitExpected, const Source&>::value));
|
||||
CHECK_FALSE((etl::is_convertible<const Source&, ExplicitExpected>::value));
|
||||
|
||||
CHECK_TRUE((etl::is_convertible<const Source&, Expected>::value));
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_explicit_error_conversion_carries_the_error)
|
||||
{
|
||||
const etl::expected<std::string, std::string> source(etl::unexpected<std::string>(std::string("failed")));
|
||||
|
||||
const etl::expected<Value, ExplicitError> result(source);
|
||||
|
||||
CHECK_FALSE(result.has_value());
|
||||
CHECK_EQUAL("failed", result.error().e);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_move_constructor_from_expected_with_convertible_types)
|
||||
{
|
||||
etl::expected<MoveOnlyValue, Error> source(MoveOnlyValue(1));
|
||||
|
||||
const etl::expected<FromMoveOnlyValue, Error> result(etl::move(source));
|
||||
|
||||
CHECK_TRUE(result.has_value());
|
||||
CHECK_EQUAL(1, result.value().v);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_move_constructor_from_expected_with_convertible_types_carries_error)
|
||||
{
|
||||
etl::expected<MoveOnlyValue, Error> source(etl::unexpected<Error>(Error("failed")));
|
||||
|
||||
const etl::expected<FromMoveOnlyValue, Error> result(etl::move(source));
|
||||
|
||||
CHECK_FALSE(result.has_value());
|
||||
CHECK_EQUAL("failed", result.error().e);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_constructor_from_value_does_not_require_a_move)
|
||||
{
|
||||
const etl::expected<NoMoveValue, Error> result(1);
|
||||
|
||||
CHECK_TRUE(result.has_value());
|
||||
CHECK_EQUAL(1, result.value().v);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_error_type_constructible_from_expected_is_not_converted)
|
||||
{
|
||||
using Source = etl::expected<int, int>;
|
||||
|
||||
CHECK_FALSE((etl::is_constructible<etl::expected<FromInt, ErrorFromExpected>, const Source&>::value));
|
||||
CHECK_FALSE((etl::is_constructible<etl::expected<FromInt, ErrorFromExpected>, Source&&>::value));
|
||||
|
||||
CHECK_TRUE((etl::is_constructible<etl::expected<FromInt, FromInt>, const Source&>::value));
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_assign_from_value_convertible_to_value_type)
|
||||
{
|
||||
Expected result;
|
||||
|
||||
result = std::string("converted");
|
||||
|
||||
CHECK_TRUE(result.has_value());
|
||||
CHECK_EQUAL("converted", result.value().v);
|
||||
}
|
||||
//*************************************************************************
|
||||
TEST(test_conversion_into_an_immobile_value_constructs_in_place)
|
||||
{
|
||||
ImmobileValue::destructions = 0;
|
||||
|
||||
{
|
||||
const etl::expected<int, Error> source(7);
|
||||
|
||||
const etl::expected<ImmobileValue, Error> result(source);
|
||||
|
||||
CHECK_TRUE(result.has_value());
|
||||
CHECK_EQUAL(7, result.value().v);
|
||||
}
|
||||
|
||||
CHECK_EQUAL(1, ImmobileValue::destructions);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_conversion_into_an_immobile_error_constructs_in_place)
|
||||
{
|
||||
ImmobileError::destructions = 0;
|
||||
|
||||
{
|
||||
const etl::expected<int, int> source(etl::unexpected<int>(9));
|
||||
|
||||
const etl::expected<FromInt, ImmobileError> result(source);
|
||||
|
||||
CHECK_FALSE(result.has_value());
|
||||
CHECK_EQUAL(9, result.error().e);
|
||||
}
|
||||
|
||||
CHECK_EQUAL(1, ImmobileError::destructions);
|
||||
}
|
||||
}
|
||||
} // namespace
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user