mirror of
https://github.com/TartanLlama/expected.git
synced 2025-08-03 19:04:29 +02:00
Support void for map_error
This commit is contained in:
63
expected.hpp
63
expected.hpp
@@ -921,9 +921,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) &;
|
||||||
@@ -975,9 +975,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) &;
|
||||||
@@ -1034,7 +1034,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.
|
||||||
@@ -1065,7 +1066,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.
|
||||||
@@ -1114,7 +1116,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.
|
||||||
@@ -1146,7 +1149,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.
|
||||||
@@ -1622,6 +1625,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>>;
|
||||||
|
|
||||||
@@ -1683,19 +1687,35 @@ 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>, 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>
|
||||||
|
constexpr 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>
|
||||||
|
constexpr auto map_error_impl(Exp &&exp, F &&f) -> expected<exp_t<Exp>, Ret> {
|
||||||
using result = ret_t<Exp, Ret>;
|
using result = ret_t<Exp, Ret>;
|
||||||
|
|
||||||
return exp.has_value()
|
return exp.has_value()
|
||||||
@@ -1703,6 +1723,21 @@ constexpr auto map_error_impl(Exp &&exp, F &&f) -> ret_t<Exp, Ret> {
|
|||||||
: 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>
|
||||||
|
constexpr 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,
|
||||||
|
@@ -191,6 +191,54 @@ 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