mirror of
https://github.com/TartanLlama/expected.git
synced 2025-08-03 19:04:29 +02:00
Merge branch 'master' into trivial_copy_fix
This commit is contained in:
@@ -11,6 +11,9 @@ target_include_directories(Catch INTERFACE ${CATCH_INCLUDE_DIR})
|
|||||||
set(TEST_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/tests/main.cpp
|
set(TEST_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/tests/main.cpp
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/tests/extensions.cpp
|
${CMAKE_CURRENT_SOURCE_DIR}/tests/extensions.cpp
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/tests/assignment.cpp
|
${CMAKE_CURRENT_SOURCE_DIR}/tests/assignment.cpp
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/tests/emplace.cpp
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/tests/bases.cpp
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/tests/observers.cpp
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/tests/constructors.cpp)
|
${CMAKE_CURRENT_SOURCE_DIR}/tests/constructors.cpp)
|
||||||
|
|
||||||
add_executable(tests ${TEST_SOURCES})
|
add_executable(tests ${TEST_SOURCES})
|
||||||
|
@@ -49,7 +49,7 @@ The interface is the same as `std::expected` as proposed in [p0323r3](http://www
|
|||||||
* `tl::expected<std::size_t,std::error_code> s = exp_string.map(&std::string::size);`
|
* `tl::expected<std::size_t,std::error_code> s = exp_string.map(&std::string::size);`
|
||||||
- `map_error`: carries out some operation on the unexpected object if there is one.
|
- `map_error`: carries out some operation on the unexpected object if there is one.
|
||||||
* `my_error_code translate_error (std::error_code);`
|
* `my_error_code translate_error (std::error_code);`
|
||||||
* `tl::expected<int,my_error_code> s = exp_int.map(translate_error);`
|
* `tl::expected<int,my_error_code> s = exp_int.map_error(translate_error);`
|
||||||
- `and_then`: like `map`, but for operations which return a `tl::expected`.
|
- `and_then`: like `map`, but for operations which return a `tl::expected`.
|
||||||
* `tl::expected<ast, fail_reason> parse (const std::string& s);`
|
* `tl::expected<ast, fail_reason> parse (const std::string& s);`
|
||||||
* `tl::expected<ast, fail_reason> exp_ast = exp_string.and_then(parse);`
|
* `tl::expected<ast, fail_reason> exp_ast = exp_string.and_then(parse);`
|
||||||
@@ -82,6 +82,10 @@ Requires [Standardese](https://github.com/foonathan/standardese) for generating
|
|||||||
|
|
||||||
Requires [Catch](https://github.com/philsquared/Catch) for testing. This is bundled in the test directory.
|
Requires [Catch](https://github.com/philsquared/Catch) for testing. This is bundled in the test directory.
|
||||||
|
|
||||||
|
### Acknowledgements
|
||||||
|
|
||||||
|
Thanks to [Kévin Alexandre Boissonneault](https://github.com/KABoissonneault) for various bug fixes.
|
||||||
|
|
||||||
----------
|
----------
|
||||||
|
|
||||||
[]("http://creativecommons.org/publicdomain/zero/1.0/")
|
[]("http://creativecommons.org/publicdomain/zero/1.0/")
|
||||||
|
91
expected.hpp
91
expected.hpp
@@ -158,8 +158,8 @@ constexpr bool operator>=(const unexpected<E> &lhs, const unexpected<E> &rhs) {
|
|||||||
/// *Example:*
|
/// *Example:*
|
||||||
/// auto e1 = tl::make_unexpected(42);
|
/// auto e1 = tl::make_unexpected(42);
|
||||||
/// unexpected<int> e2 (42); //same semantics
|
/// unexpected<int> e2 (42); //same semantics
|
||||||
template <class E> unexpected<E> make_unexpected(E &&e) {
|
template <class E> unexpected<typename std::decay<E>::type> make_unexpected(E &&e) {
|
||||||
return unexpected<E>(std::forward<E>(e));
|
return unexpected<typename std::decay<E>::type>(std::forward<E>(e));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// \brief A tag type to tell expected to construct the unexpected value
|
/// \brief A tag type to tell expected to construct the unexpected value
|
||||||
@@ -631,7 +631,8 @@ struct expected_copy_base<T, E, false> : expected_operations_base<T, E> {
|
|||||||
// move constructible
|
// move constructible
|
||||||
#ifndef TL_EXPECTED_GCC49
|
#ifndef TL_EXPECTED_GCC49
|
||||||
template <class T, class E,
|
template <class T, class E,
|
||||||
bool = std::is_trivially_move_constructible<T>::value>
|
bool = std::is_trivially_move_constructible<T>::value
|
||||||
|
&& std::is_trivially_move_constructible<E>::value>
|
||||||
struct expected_move_base : expected_copy_base<T, E> {
|
struct expected_move_base : expected_copy_base<T, E> {
|
||||||
using expected_copy_base<T, E>::expected_copy_base;
|
using expected_copy_base<T, E>::expected_copy_base;
|
||||||
};
|
};
|
||||||
@@ -662,7 +663,10 @@ struct expected_move_base<T, E, false> : expected_copy_base<T, E> {
|
|||||||
template <class T, class E,
|
template <class T, class E,
|
||||||
bool = IS_TRIVIALLY_COPY_ASSIGNABLE(T) &&
|
bool = IS_TRIVIALLY_COPY_ASSIGNABLE(T) &&
|
||||||
IS_TRIVIALLY_COPY_CONSTRUCTIBLE(T) &&
|
IS_TRIVIALLY_COPY_CONSTRUCTIBLE(T) &&
|
||||||
IS_TRIVIALLY_DESTRUCTIBLE(T)>
|
IS_TRIVIALLY_DESTRUCTIBLE(T) &&
|
||||||
|
IS_TRIVIALLY_COPY_ASSIGNABLE(E) &&
|
||||||
|
IS_TRIVIALLY_COPY_CONSTRUCTIBLE(E) &&
|
||||||
|
IS_TRIVIALLY_DESTRUCTIBLE(E)>
|
||||||
struct expected_copy_assign_base : expected_move_base<T, E> {
|
struct expected_copy_assign_base : expected_move_base<T, E> {
|
||||||
using expected_move_base<T, E>::expected_move_base;
|
using expected_move_base<T, E>::expected_move_base;
|
||||||
};
|
};
|
||||||
@@ -692,7 +696,10 @@ struct expected_copy_assign_base<T, E, false> : expected_move_base<T, E> {
|
|||||||
template <class T, class E,
|
template <class T, class E,
|
||||||
bool = std::is_trivially_destructible<T>::value
|
bool = std::is_trivially_destructible<T>::value
|
||||||
&&std::is_trivially_move_constructible<T>::value
|
&&std::is_trivially_move_constructible<T>::value
|
||||||
&&std::is_trivially_move_assignable<T>::value>
|
&&std::is_trivially_move_assignable<T>::value
|
||||||
|
&&std::is_trivially_destructible<E>::value
|
||||||
|
&&std::is_trivially_move_constructible<E>::value
|
||||||
|
&&std::is_trivially_move_assignable<E>::value>
|
||||||
struct expected_move_assign_base : expected_copy_assign_base<T, E> {
|
struct expected_move_assign_base : expected_copy_assign_base<T, E> {
|
||||||
using expected_copy_assign_base<T, E>::expected_copy_assign_base;
|
using expected_copy_assign_base<T, E>::expected_copy_assign_base;
|
||||||
};
|
};
|
||||||
@@ -709,9 +716,12 @@ struct expected_move_assign_base<T, E, false>
|
|||||||
expected_move_assign_base(const expected_move_assign_base &rhs) = default;
|
expected_move_assign_base(const expected_move_assign_base &rhs) = default;
|
||||||
|
|
||||||
expected_move_assign_base(expected_move_assign_base &&rhs) = default;
|
expected_move_assign_base(expected_move_assign_base &&rhs) = default;
|
||||||
|
|
||||||
expected_move_assign_base &
|
expected_move_assign_base &
|
||||||
operator=(const expected_move_assign_base &rhs) = default;
|
operator=(const expected_move_assign_base &rhs) = default;
|
||||||
|
|
||||||
expected_move_assign_base &
|
expected_move_assign_base &
|
||||||
|
|
||||||
operator=(expected_move_assign_base &&rhs) noexcept(
|
operator=(expected_move_assign_base &&rhs) noexcept(
|
||||||
std::is_nothrow_move_constructible<T>::value
|
std::is_nothrow_move_constructible<T>::value
|
||||||
&&std::is_nothrow_move_assignable<T>::value) {
|
&&std::is_nothrow_move_assignable<T>::value) {
|
||||||
@@ -929,9 +939,9 @@ public:
|
|||||||
/// \group and_then
|
/// \group and_then
|
||||||
/// Carries out some operation which returns an expected on the stored object
|
/// Carries out some operation which returns an expected on the stored object
|
||||||
/// if there is one. \requires `std::invoke(std::forward<F>(f), value())`
|
/// if there is one. \requires `std::invoke(std::forward<F>(f), value())`
|
||||||
/// returns a `std::expected<U>` for some `U`. \returns Let `U` be the result
|
/// returns an `expected<U>` for some `U`. \returns Let `U` be the result
|
||||||
/// of `std::invoke(std::forward<F>(f), value())`. Returns a
|
/// of `std::invoke(std::forward<F>(f), value())`. Returns an
|
||||||
/// `std::expected<U>`. The return value is empty if `*this` is empty,
|
/// `expected<U>`. The return value is empty if `*this` is empty,
|
||||||
/// otherwise the return value of `std::invoke(std::forward<F>(f), value())`
|
/// otherwise the return value of `std::invoke(std::forward<F>(f), value())`
|
||||||
/// is returned.
|
/// is returned.
|
||||||
/// \synopsis template <class F>\nconstexpr auto and_then(F &&f) &;
|
/// \synopsis template <class F>\nconstexpr auto and_then(F &&f) &;
|
||||||
@@ -983,9 +993,9 @@ public:
|
|||||||
/// \group and_then
|
/// \group and_then
|
||||||
/// Carries out some operation which returns an expected on the stored object
|
/// Carries out some operation which returns an expected on the stored object
|
||||||
/// if there is one. \requires `std::invoke(std::forward<F>(f), value())`
|
/// if there is one. \requires `std::invoke(std::forward<F>(f), value())`
|
||||||
/// returns a `std::expected<U>` for some `U`. \returns Let `U` be the result
|
/// returns an `expected<U>` for some `U`. \returns Let `U` be the result
|
||||||
/// of `std::invoke(std::forward<F>(f), value())`. Returns a
|
/// of `std::invoke(std::forward<F>(f), value())`. Returns an
|
||||||
/// `std::expected<U>`. The return value is empty if `*this` is empty,
|
/// `expected<U>`. The return value is empty if `*this` is empty,
|
||||||
/// otherwise the return value of `std::invoke(std::forward<F>(f), value())`
|
/// otherwise the return value of `std::invoke(std::forward<F>(f), value())`
|
||||||
/// is returned.
|
/// is returned.
|
||||||
/// \synopsis template <class F>\nconstexpr auto and_then(F &&f) &;
|
/// \synopsis template <class F>\nconstexpr auto and_then(F &&f) &;
|
||||||
@@ -1042,7 +1052,8 @@ public:
|
|||||||
!defined(TL_EXPECTED_GCC54)
|
!defined(TL_EXPECTED_GCC54)
|
||||||
/// \brief Carries out some operation on the stored object if there is one.
|
/// \brief Carries out some operation on the stored object if there is one.
|
||||||
/// \returns Let `U` be the result of `std::invoke(std::forward<F>(f),
|
/// \returns Let `U` be the result of `std::invoke(std::forward<F>(f),
|
||||||
/// value())`. Returns a `std::expected<U,E>`. If `*this` is unexpected, the
|
/// value())`. If `U` is `void`, returns an `expected<monostate,E>, otherwise
|
||||||
|
// returns an `expected<U,E>`. If `*this` is unexpected, the
|
||||||
/// result is `*this`, otherwise an `expected<U,E>` is constructed from the
|
/// result is `*this`, otherwise an `expected<U,E>` is constructed from the
|
||||||
/// return value of `std::invoke(std::forward<F>(f), value())` and is
|
/// return value of `std::invoke(std::forward<F>(f), value())` and is
|
||||||
/// returned.
|
/// returned.
|
||||||
@@ -1073,7 +1084,8 @@ public:
|
|||||||
#else
|
#else
|
||||||
/// \brief Carries out some operation on the stored object if there is one.
|
/// \brief Carries out some operation on the stored object if there is one.
|
||||||
/// \returns Let `U` be the result of `std::invoke(std::forward<F>(f),
|
/// \returns Let `U` be the result of `std::invoke(std::forward<F>(f),
|
||||||
/// value())`. Returns a `std::expected<U,E>`. If `*this` is unexpected, the
|
/// value())`. If `U` is `void`, returns an `expected<monostate,E>, otherwise
|
||||||
|
// returns an `expected<U,E>`. If `*this` is unexpected, the
|
||||||
/// result is `*this`, otherwise an `expected<U,E>` is constructed from the
|
/// result is `*this`, otherwise an `expected<U,E>` is constructed from the
|
||||||
/// return value of `std::invoke(std::forward<F>(f), value())` and is
|
/// return value of `std::invoke(std::forward<F>(f), value())` and is
|
||||||
/// returned.
|
/// returned.
|
||||||
@@ -1122,7 +1134,8 @@ public:
|
|||||||
/// \brief Carries out some operation on the stored unexpected object if there
|
/// \brief Carries out some operation on the stored unexpected object if there
|
||||||
/// is one.
|
/// is one.
|
||||||
/// \returns Let `U` be the result of `std::invoke(std::forward<F>(f),
|
/// \returns Let `U` be the result of `std::invoke(std::forward<F>(f),
|
||||||
/// value())`. Returns a `std::expected<T,U>`. If `*this` has an expected
|
/// value())`. If `U` is `void`, returns an `expected<T,monostate>`, otherwise
|
||||||
|
/// returns an `expected<T,U>`. If `*this` has an expected
|
||||||
/// value, the result is `*this`, otherwise an `expected<T,U>` is constructed
|
/// value, the result is `*this`, otherwise an `expected<T,U>` is constructed
|
||||||
/// from `make_unexpected(std::invoke(std::forward<F>(f), value()))` and is
|
/// from `make_unexpected(std::invoke(std::forward<F>(f), value()))` and is
|
||||||
/// returned.
|
/// returned.
|
||||||
@@ -1154,7 +1167,7 @@ public:
|
|||||||
/// \brief Carries out some operation on the stored unexpected object if there
|
/// \brief Carries out some operation on the stored unexpected object if there
|
||||||
/// is one.
|
/// is one.
|
||||||
/// \returns Let `U` be the result of `std::invoke(std::forward<F>(f),
|
/// \returns Let `U` be the result of `std::invoke(std::forward<F>(f),
|
||||||
/// value())`. Returns a `std::expected<T,U>`. If `*this` has an expected
|
/// value())`. Returns an `expected<T,U>`. If `*this` has an expected
|
||||||
/// value, the result is `*this`, otherwise an `expected<T,U>` is constructed
|
/// value, the result is `*this`, otherwise an `expected<T,U>` is constructed
|
||||||
/// from `make_unexpected(std::invoke(std::forward<F>(f), value()))` and is
|
/// from `make_unexpected(std::invoke(std::forward<F>(f), value()))` and is
|
||||||
/// returned.
|
/// returned.
|
||||||
@@ -1630,6 +1643,7 @@ public:
|
|||||||
|
|
||||||
/// \exclude
|
/// \exclude
|
||||||
namespace detail {
|
namespace detail {
|
||||||
|
template <class Exp> using exp_t = typename detail::decay_t<Exp>::error_type;
|
||||||
template <class Exp> using err_t = typename detail::decay_t<Exp>::error_type;
|
template <class Exp> using err_t = typename detail::decay_t<Exp>::error_type;
|
||||||
template <class Exp, class Ret> using ret_t = expected<Ret, err_t<Exp>>;
|
template <class Exp, class Ret> using ret_t = expected<Ret, err_t<Exp>>;
|
||||||
|
|
||||||
@@ -1639,7 +1653,7 @@ template <class Exp, class F,
|
|||||||
*std::declval<Exp>())),
|
*std::declval<Exp>())),
|
||||||
detail::enable_if_t<!std::is_void<Ret>::value> * = nullptr>
|
detail::enable_if_t<!std::is_void<Ret>::value> * = nullptr>
|
||||||
constexpr auto map_impl(Exp &&exp, F &&f) {
|
constexpr auto map_impl(Exp &&exp, F &&f) {
|
||||||
using result = ret_t<Exp, Ret>;
|
using result = ret_t<Exp, detail::decay_t<Ret>>;
|
||||||
return exp.has_value() ? result(detail::invoke(std::forward<F>(f),
|
return exp.has_value() ? result(detail::invoke(std::forward<F>(f),
|
||||||
*std::forward<Exp>(exp)))
|
*std::forward<Exp>(exp)))
|
||||||
: result(unexpect, std::forward<Exp>(exp).error());
|
: result(unexpect, std::forward<Exp>(exp).error());
|
||||||
@@ -1664,8 +1678,8 @@ template <class Exp, class F,
|
|||||||
*std::declval<Exp>())),
|
*std::declval<Exp>())),
|
||||||
detail::enable_if_t<!std::is_void<Ret>::value> * = nullptr>
|
detail::enable_if_t<!std::is_void<Ret>::value> * = nullptr>
|
||||||
|
|
||||||
constexpr auto map_impl(Exp &&exp, F &&f) -> ret_t<Exp, Ret> {
|
constexpr auto map_impl(Exp &&exp, F &&f) -> ret_t<Exp, detail::decay_t<Ret>> {
|
||||||
using result = ret_t<Exp, Ret>;
|
using result = ret_t<Exp, detail::decay_t<Ret>>;
|
||||||
|
|
||||||
return exp.has_value() ? result(detail::invoke(std::forward<F>(f),
|
return exp.has_value() ? result(detail::invoke(std::forward<F>(f),
|
||||||
*std::forward<Exp>(exp)))
|
*std::forward<Exp>(exp)))
|
||||||
@@ -1691,26 +1705,57 @@ auto map_impl(Exp &&exp, F &&f) -> expected<monostate, err_t<Exp>> {
|
|||||||
!defined(TL_EXPECTED_GCC54)
|
!defined(TL_EXPECTED_GCC54)
|
||||||
template <class Exp, class F,
|
template <class Exp, class F,
|
||||||
class Ret = decltype(detail::invoke(std::declval<F>(),
|
class Ret = decltype(detail::invoke(std::declval<F>(),
|
||||||
*std::declval<Exp>()))>
|
*std::declval<Exp>())),
|
||||||
|
detail::enable_if_t<!std::is_void<Ret>::value> * = nullptr>
|
||||||
constexpr auto map_error_impl(Exp &&exp, F &&f) {
|
constexpr auto map_error_impl(Exp &&exp, F &&f) {
|
||||||
using result = ret_t<Exp, Ret>;
|
using result = expected<exp_t<Exp>, detail::decay_t<Ret>>;
|
||||||
return exp.has_value()
|
return exp.has_value()
|
||||||
? result(*std::forward<Exp>(exp))
|
? result(*std::forward<Exp>(exp))
|
||||||
: result(unexpect, detail::invoke(std::forward<F>(f),
|
: result(unexpect, detail::invoke(std::forward<F>(f),
|
||||||
std::forward<Exp>(exp).error()));
|
std::forward<Exp>(exp).error()));
|
||||||
}
|
}
|
||||||
|
template <class Exp, class F,
|
||||||
|
class Ret = decltype(detail::invoke(std::declval<F>(),
|
||||||
|
*std::declval<Exp>())),
|
||||||
|
detail::enable_if_t<std::is_void<Ret>::value> * = nullptr>
|
||||||
|
auto map_error_impl(Exp &&exp, F &&f) {
|
||||||
|
using result = expected<exp_t<Exp>, monostate>;
|
||||||
|
if (exp.has_value()) {
|
||||||
|
return result(*std::forward<Exp>(exp));
|
||||||
|
}
|
||||||
|
|
||||||
|
detail::invoke(std::forward<F>(f),
|
||||||
|
std::forward<Exp>(exp).error());
|
||||||
|
return result(unexpect, monostate{});
|
||||||
|
}
|
||||||
#else
|
#else
|
||||||
template <class Exp, class F,
|
template <class Exp, class F,
|
||||||
class Ret = decltype(detail::invoke(std::declval<F>(),
|
class Ret = decltype(detail::invoke(std::declval<F>(),
|
||||||
*std::declval<Exp>()))>
|
*std::declval<Exp>())),
|
||||||
constexpr auto map_error_impl(Exp &&exp, F &&f) -> ret_t<Exp, Ret> {
|
detail::enable_if_t<!std::is_void<Ret>::value> * = nullptr>
|
||||||
using result = ret_t<Exp, Ret>;
|
constexpr auto map_error_impl(Exp &&exp, F &&f) -> expected<exp_t<Exp>, detail::decay_t<Ret>> {
|
||||||
|
using result = ret_t<Exp, detail::decay_t<Ret>>;
|
||||||
|
|
||||||
return exp.has_value()
|
return exp.has_value()
|
||||||
? result(*std::forward<Exp>(exp))
|
? result(*std::forward<Exp>(exp))
|
||||||
: result(unexpect, detail::invoke(std::forward<F>(f),
|
: result(unexpect, detail::invoke(std::forward<F>(f),
|
||||||
std::forward<Exp>(exp).error()));
|
std::forward<Exp>(exp).error()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <class Exp, class F,
|
||||||
|
class Ret = decltype(detail::invoke(std::declval<F>(),
|
||||||
|
*std::declval<Exp>())),
|
||||||
|
detail::enable_if_t<std::is_void<Ret>::value> * = nullptr>
|
||||||
|
auto map_error_impl(Exp &&exp, F &&f) -> expected<exp_t<Exp>, monostate> {
|
||||||
|
using result = expected<exp_t<Exp>, monostate>;
|
||||||
|
if (exp.has_value()) {
|
||||||
|
return result(*std::forward<Exp>(exp));
|
||||||
|
}
|
||||||
|
|
||||||
|
detail::invoke(std::forward<F>(f),
|
||||||
|
std::forward<Exp>(exp).error());
|
||||||
|
return result(unexpect, monostate{});
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
template <class Exp, class F,
|
template <class Exp, class F,
|
||||||
|
@@ -130,6 +130,15 @@ TEST_CASE("Map extensions", "[extensions.map]") {
|
|||||||
STATIC_REQUIRE(
|
STATIC_REQUIRE(
|
||||||
(std::is_same<decltype(ret), tl::expected<tl::monostate, int>>::value));
|
(std::is_same<decltype(ret), tl::expected<tl::monostate, int>>::value));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// mapping functions which return references
|
||||||
|
{
|
||||||
|
tl::expected<int, int> e(42);
|
||||||
|
auto ret = e.map([](int& i) -> int& { return i; });
|
||||||
|
REQUIRE(ret);
|
||||||
|
REQUIRE(ret == 42);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("Map error extensions", "[extensions.map_error]") {
|
TEST_CASE("Map error extensions", "[extensions.map_error]") {
|
||||||
@@ -191,6 +200,55 @@ TEST_CASE("Map error extensions", "[extensions.map_error]") {
|
|||||||
REQUIRE(!ret);
|
REQUIRE(!ret);
|
||||||
REQUIRE(ret.error() == 42);
|
REQUIRE(ret.error() == 42);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
tl::expected<int, int> e = 21;
|
||||||
|
auto ret = e.map_error(ret_void);
|
||||||
|
REQUIRE(ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
const tl::expected<int, int> e = 21;
|
||||||
|
auto ret = e.map_error(ret_void);
|
||||||
|
REQUIRE(ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
tl::expected<int, int> e = 21;
|
||||||
|
auto ret = std::move(e).map_error(ret_void);
|
||||||
|
REQUIRE(ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
const tl::expected<int, int> e = 21;
|
||||||
|
auto ret = std::move(e).map_error(ret_void);
|
||||||
|
REQUIRE(ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
tl::expected<int, int> e(tl::unexpect, 21);
|
||||||
|
auto ret = e.map_error(ret_void);
|
||||||
|
REQUIRE(!ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
const tl::expected<int, int> e(tl::unexpect, 21);
|
||||||
|
auto ret = e.map_error(ret_void);
|
||||||
|
REQUIRE(!ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
tl::expected<int, int> e(tl::unexpect, 21);
|
||||||
|
auto ret = std::move(e).map_error(ret_void);
|
||||||
|
REQUIRE(!ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
const tl::expected<int, int> e(tl::unexpect, 21);
|
||||||
|
auto ret = std::move(e).map_error(ret_void);
|
||||||
|
REQUIRE(!ret);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("And then extensions", "[extensions.and_then]") {
|
TEST_CASE("And then extensions", "[extensions.and_then]") {
|
||||||
|
Reference in New Issue
Block a user