forked from TartanLlama/expected
Remove extensions
This commit is contained in:
@ -9,10 +9,8 @@ target_include_directories(Catch INTERFACE ${CATCH_INCLUDE_DIR})
|
|||||||
|
|
||||||
# Make test executable
|
# Make test executable
|
||||||
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/assignment.cpp
|
${CMAKE_CURRENT_SOURCE_DIR}/tests/assignment.cpp
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/tests/emplace.cpp
|
${CMAKE_CURRENT_SOURCE_DIR}/tests/emplace.cpp
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/tests/issues.cpp
|
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/tests/bases.cpp
|
${CMAKE_CURRENT_SOURCE_DIR}/tests/bases.cpp
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/tests/observers.cpp
|
${CMAKE_CURRENT_SOURCE_DIR}/tests/observers.cpp
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/tests/constructors.cpp)
|
${CMAKE_CURRENT_SOURCE_DIR}/tests/constructors.cpp)
|
||||||
|
458
tl/expected.hpp
458
tl/expected.hpp
@ -1080,271 +1080,6 @@ public:
|
|||||||
typedef E error_type;
|
typedef E error_type;
|
||||||
typedef unexpected<E> unexpected_type;
|
typedef unexpected<E> unexpected_type;
|
||||||
|
|
||||||
#if defined(TL_EXPECTED_CXX14) && !defined(TL_EXPECTED_GCC49) && \
|
|
||||||
!defined(TL_EXPECTED_GCC54)
|
|
||||||
/// \group and_then
|
|
||||||
/// Carries out some operation which returns an expected on the stored object
|
|
||||||
/// if there is one. \requires `std::invoke(std::forward<F>(f), value())`
|
|
||||||
/// returns an `expected<U>` for some `U`. \returns Let `U` be the result
|
|
||||||
/// of `std::invoke(std::forward<F>(f), value())`. Returns an
|
|
||||||
/// `expected<U>`. The return value is empty if `*this` is empty,
|
|
||||||
/// otherwise the return value of `std::invoke(std::forward<F>(f), value())`
|
|
||||||
/// is returned.
|
|
||||||
/// \synopsis template <class F>\nconstexpr auto and_then(F &&f) &;
|
|
||||||
template <class F> TL_EXPECTED_11_CONSTEXPR auto and_then(F &&f) & {
|
|
||||||
return and_then_impl(*this, std::forward<F>(f));
|
|
||||||
}
|
|
||||||
|
|
||||||
/// \group and_then
|
|
||||||
/// \synopsis template <class F>\nconstexpr auto and_then(F &&f) &&;
|
|
||||||
template <class F> TL_EXPECTED_11_CONSTEXPR auto and_then(F &&f) && {
|
|
||||||
return and_then_impl(std::move(*this), std::forward<F>(f));
|
|
||||||
}
|
|
||||||
|
|
||||||
/// \group and_then
|
|
||||||
/// \synopsis template <class F>\nconstexpr auto and_then(F &&f) const &;
|
|
||||||
template <class F> constexpr auto and_then(F &&f) const & {
|
|
||||||
return and_then_impl(*this, std::forward<F>(f));
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifndef TL_EXPECTED_NO_CONSTRR
|
|
||||||
/// \group and_then
|
|
||||||
/// \synopsis template <class F>\nconstexpr auto and_then(F &&f) const &&;
|
|
||||||
template <class F> constexpr auto and_then(F &&f) const && {
|
|
||||||
return and_then_impl(std::move(*this), std::forward<F>(f));
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#else
|
|
||||||
/// \group and_then
|
|
||||||
/// Carries out some operation which returns an expected on the stored object
|
|
||||||
/// if there is one. \requires `std::invoke(std::forward<F>(f), value())`
|
|
||||||
/// returns an `expected<U>` for some `U`. \returns Let `U` be the result
|
|
||||||
/// of `std::invoke(std::forward<F>(f), value())`. Returns an
|
|
||||||
/// `expected<U>`. The return value is empty if `*this` is empty,
|
|
||||||
/// otherwise the return value of `std::invoke(std::forward<F>(f), value())`
|
|
||||||
/// is returned.
|
|
||||||
/// \synopsis template <class F>\nconstexpr auto and_then(F &&f) &;
|
|
||||||
template <class F>
|
|
||||||
TL_EXPECTED_11_CONSTEXPR auto
|
|
||||||
and_then(F &&f) & -> decltype(and_then_impl(*this, std::forward<F>(f))) {
|
|
||||||
return and_then_impl(*this, std::forward<F>(f));
|
|
||||||
}
|
|
||||||
|
|
||||||
/// \group and_then
|
|
||||||
/// \synopsis template <class F>\nconstexpr auto and_then(F &&f) &&;
|
|
||||||
template <class F>
|
|
||||||
TL_EXPECTED_11_CONSTEXPR auto and_then(F &&f) && -> decltype(
|
|
||||||
and_then_impl(std::move(*this), std::forward<F>(f))) {
|
|
||||||
return and_then_impl(std::move(*this), std::forward<F>(f));
|
|
||||||
}
|
|
||||||
|
|
||||||
/// \group and_then
|
|
||||||
/// \synopsis template <class F>\nconstexpr auto and_then(F &&f) const &;
|
|
||||||
template <class F>
|
|
||||||
constexpr auto and_then(F &&f) const & -> decltype(
|
|
||||||
and_then_impl(*this, std::forward<F>(f))) {
|
|
||||||
return and_then_impl(*this, std::forward<F>(f));
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifndef TL_EXPECTED_NO_CONSTRR
|
|
||||||
/// \group and_then
|
|
||||||
/// \synopsis template <class F>\nconstexpr auto and_then(F &&f) const &&;
|
|
||||||
template <class F>
|
|
||||||
constexpr auto and_then(F &&f) const && -> decltype(
|
|
||||||
and_then_impl(std::move(*this), std::forward<F>(f))) {
|
|
||||||
return and_then_impl(std::move(*this), std::forward<F>(f));
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(TL_EXPECTED_CXX14) && !defined(TL_EXPECTED_GCC49) && \
|
|
||||||
!defined(TL_EXPECTED_GCC54)
|
|
||||||
/// \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),
|
|
||||||
/// 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
|
|
||||||
/// return value of `std::invoke(std::forward<F>(f), value())` and is
|
|
||||||
/// returned.
|
|
||||||
///
|
|
||||||
/// \group map
|
|
||||||
/// \synopsis template <class F> constexpr auto map(F &&f) &;
|
|
||||||
template <class F> TL_EXPECTED_11_CONSTEXPR auto map(F &&f) & {
|
|
||||||
return expected_map_impl(*this, std::forward<F>(f));
|
|
||||||
}
|
|
||||||
|
|
||||||
/// \group map
|
|
||||||
/// \synopsis template <class F> constexpr auto map(F &&f) &&;
|
|
||||||
template <class F> TL_EXPECTED_11_CONSTEXPR auto map(F &&f) && {
|
|
||||||
return expected_map_impl(std::move(*this), std::forward<F>(f));
|
|
||||||
}
|
|
||||||
|
|
||||||
/// \group map
|
|
||||||
/// \synopsis template <class F> constexpr auto map(F &&f) const &;
|
|
||||||
template <class F> constexpr auto map(F &&f) const & {
|
|
||||||
return expected_map_impl(*this, std::forward<F>(f));
|
|
||||||
}
|
|
||||||
|
|
||||||
/// \group map
|
|
||||||
/// \synopsis template <class F> constexpr auto map(F &&f) const &&;
|
|
||||||
template <class F> constexpr auto map(F &&f) const && {
|
|
||||||
return expected_map_impl(std::move(*this), std::forward<F>(f));
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
/// \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),
|
|
||||||
/// 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
|
|
||||||
/// return value of `std::invoke(std::forward<F>(f), value())` and is
|
|
||||||
/// returned.
|
|
||||||
///
|
|
||||||
/// \group map
|
|
||||||
/// \synopsis template <class F> constexpr auto map(F &&f) &;
|
|
||||||
template <class F>
|
|
||||||
TL_EXPECTED_11_CONSTEXPR decltype(
|
|
||||||
expected_map_impl(std::declval<expected &>(), std::declval<F &&>()))
|
|
||||||
map(F &&f) & {
|
|
||||||
return expected_map_impl(*this, std::forward<F>(f));
|
|
||||||
}
|
|
||||||
|
|
||||||
/// \group map
|
|
||||||
/// \synopsis template <class F> constexpr auto map(F &&f) &&;
|
|
||||||
template <class F>
|
|
||||||
TL_EXPECTED_11_CONSTEXPR decltype(
|
|
||||||
expected_map_impl(std::declval<expected &>(), std::declval<F &&>()))
|
|
||||||
map(F &&f) && {
|
|
||||||
return expected_map_impl(std::move(*this), std::forward<F>(f));
|
|
||||||
}
|
|
||||||
|
|
||||||
/// \group map
|
|
||||||
/// \synopsis template <class F> constexpr auto map(F &&f) const &;
|
|
||||||
template <class F>
|
|
||||||
constexpr decltype(expected_map_impl(std::declval<const expected &>(),
|
|
||||||
std::declval<F &&>()))
|
|
||||||
map(F &&f) const & {
|
|
||||||
return expected_map_impl(*this, std::forward<F>(f));
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifndef TL_EXPECTED_NO_CONSTRR
|
|
||||||
/// \group map
|
|
||||||
/// \synopsis template <class F> constexpr auto map(F &&f) const &&;
|
|
||||||
template <class F>
|
|
||||||
constexpr decltype(expected_map_impl(std::declval<const expected &&>(),
|
|
||||||
std::declval<F &&>()))
|
|
||||||
map(F &&f) const && {
|
|
||||||
return expected_map_impl(std::move(*this), std::forward<F>(f));
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(TL_EXPECTED_CXX14) && !defined(TL_EXPECTED_GCC49) && \
|
|
||||||
!defined(TL_EXPECTED_GCC54)
|
|
||||||
/// \brief Carries out some operation on the stored unexpected object if there
|
|
||||||
/// is one.
|
|
||||||
/// \returns Let `U` be the result of `std::invoke(std::forward<F>(f),
|
|
||||||
/// 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
|
|
||||||
/// from `make_unexpected(std::invoke(std::forward<F>(f), value()))` and is
|
|
||||||
/// returned.
|
|
||||||
///
|
|
||||||
/// \group map_error
|
|
||||||
/// \synopsis template <class F> constexpr auto map_error(F &&f) &;
|
|
||||||
template <class F> TL_EXPECTED_11_CONSTEXPR auto map_error(F &&f) & {
|
|
||||||
return map_error_impl(*this, std::forward<F>(f));
|
|
||||||
}
|
|
||||||
|
|
||||||
/// \group map_error
|
|
||||||
/// \synopsis template <class F> constexpr auto map_error(F &&f) &&;
|
|
||||||
template <class F> TL_EXPECTED_11_CONSTEXPR auto map_error(F &&f) && {
|
|
||||||
return map_error_impl(std::move(*this), std::forward<F>(f));
|
|
||||||
}
|
|
||||||
|
|
||||||
/// \group map_error
|
|
||||||
/// \synopsis template <class F> constexpr auto map_error(F &&f) const &;
|
|
||||||
template <class F> constexpr auto map_error(F &&f) const & {
|
|
||||||
return map_error_impl(*this, std::forward<F>(f));
|
|
||||||
}
|
|
||||||
|
|
||||||
/// \group map_error
|
|
||||||
/// \synopsis template <class F> constexpr auto map_error(F &&f) const &&;
|
|
||||||
template <class F> constexpr auto map_error(F &&f) const && {
|
|
||||||
return map_error_impl(std::move(*this), std::forward<F>(f));
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
/// \brief Carries out some operation on the stored unexpected object if there
|
|
||||||
/// is one.
|
|
||||||
/// \returns Let `U` be the result of `std::invoke(std::forward<F>(f),
|
|
||||||
/// value())`. Returns an `expected<T,U>`. If `*this` has an expected
|
|
||||||
/// value, the result is `*this`, otherwise an `expected<T,U>` is constructed
|
|
||||||
/// from `make_unexpected(std::invoke(std::forward<F>(f), value()))` and is
|
|
||||||
/// returned.
|
|
||||||
///
|
|
||||||
/// \group map_error
|
|
||||||
/// \synopsis template <class F> constexpr auto map_error(F &&f) &;
|
|
||||||
template <class F>
|
|
||||||
TL_EXPECTED_11_CONSTEXPR decltype(map_error_impl(std::declval<expected &>(),
|
|
||||||
std::declval<F &&>()))
|
|
||||||
map_error(F &&f) & {
|
|
||||||
return map_error_impl(*this, std::forward<F>(f));
|
|
||||||
}
|
|
||||||
|
|
||||||
/// \group map_error
|
|
||||||
/// \synopsis template <class F> constexpr auto map_error(F &&f) &&;
|
|
||||||
template <class F>
|
|
||||||
TL_EXPECTED_11_CONSTEXPR decltype(map_error_impl(std::declval<expected &&>(),
|
|
||||||
std::declval<F &&>()))
|
|
||||||
map_error(F &&f) && {
|
|
||||||
return map_error_impl(std::move(*this), std::forward<F>(f));
|
|
||||||
}
|
|
||||||
|
|
||||||
/// \group map_error
|
|
||||||
/// \synopsis template <class F> constexpr auto map_error(F &&f) const &;
|
|
||||||
template <class F>
|
|
||||||
constexpr decltype(map_error_impl(std::declval<const expected &>(),
|
|
||||||
std::declval<F &&>()))
|
|
||||||
map_error(F &&f) const & {
|
|
||||||
return map_error_impl(*this, std::forward<F>(f));
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifndef TL_EXPECTED_NO_CONSTRR
|
|
||||||
/// \group map_error
|
|
||||||
/// \synopsis template <class F> constexpr auto map_error(F &&f) const &&;
|
|
||||||
template <class F>
|
|
||||||
constexpr decltype(map_error_impl(std::declval<const expected &&>(),
|
|
||||||
std::declval<F &&>()))
|
|
||||||
map_error(F &&f) const && {
|
|
||||||
return map_error_impl(std::move(*this), std::forward<F>(f));
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/// \brief Calls `f` if the expectd is in the unexpected state
|
|
||||||
/// \requires `std::invoke_result_t<F>` must be void or convertible to
|
|
||||||
/// `expcted<T,E>`.
|
|
||||||
/// \effects If `*this` has a value, returns `*this`.
|
|
||||||
/// Otherwise, if `f` returns `void`, calls `std::forward<F>(f)` and returns
|
|
||||||
/// `std::nullopt`. Otherwise, returns `std::forward<F>(f)()`.
|
|
||||||
///
|
|
||||||
/// \group or_else
|
|
||||||
template <class F> expected TL_EXPECTED_11_CONSTEXPR or_else(F &&f) & {
|
|
||||||
return or_else_impl(*this, std::forward<F>(f));
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class F> expected TL_EXPECTED_11_CONSTEXPR or_else(F &&f) && {
|
|
||||||
return or_else_impl(std::move(*this), std::forward<F>(f));
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class F> expected constexpr or_else(F &&f) const & {
|
|
||||||
return or_else_impl(*this, std::forward<F>(f));
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class F> expected constexpr or_else(F &&f) const && {
|
|
||||||
return or_else_impl(std::move(*this), std::forward<F>(f));
|
|
||||||
}
|
|
||||||
|
|
||||||
constexpr expected() = default;
|
constexpr expected() = default;
|
||||||
constexpr expected(const expected &rhs) = default;
|
constexpr expected(const expected &rhs) = default;
|
||||||
constexpr expected(expected &&rhs) = default;
|
constexpr expected(expected &&rhs) = default;
|
||||||
@ -1780,199 +1515,6 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/// \exclude
|
|
||||||
namespace detail {
|
|
||||||
template <class Exp> using exp_t = typename detail::decay_t<Exp>::value_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>>;
|
|
||||||
|
|
||||||
#ifdef TL_EXPECTED_CXX14
|
|
||||||
template <class Exp, class F,
|
|
||||||
class Ret = decltype(detail::invoke(std::declval<F>(),
|
|
||||||
*std::declval<Exp>())),
|
|
||||||
detail::enable_if_t<!std::is_void<exp_t<Exp>>::value> * = nullptr>
|
|
||||||
constexpr auto and_then_impl(Exp &&exp, F &&f) {
|
|
||||||
static_assert(detail::is_expected<Ret>::value, "F must return an expected");
|
|
||||||
|
|
||||||
return exp.has_value()
|
|
||||||
? detail::invoke(std::forward<F>(f), *std::forward<Exp>(exp))
|
|
||||||
: Ret(unexpect, 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<exp_t<Exp>>::value> * = nullptr>
|
|
||||||
constexpr auto and_then_impl(Exp &&exp, F &&f) {
|
|
||||||
static_assert(detail::is_expected<Ret>::value, "F must return an expected");
|
|
||||||
|
|
||||||
return exp.has_value() ? detail::invoke(std::forward<F>(f))
|
|
||||||
: Ret(unexpect, exp.error());
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
template <class> struct TC;
|
|
||||||
template <class Exp, class F,
|
|
||||||
class Ret = decltype(detail::invoke(std::declval<F>(),
|
|
||||||
*std::declval<Exp>())),
|
|
||||||
detail::enable_if_t<!std::is_void<exp_t<Exp>>::value> * = nullptr>
|
|
||||||
auto and_then_impl(Exp &&exp, F &&f) -> Ret {
|
|
||||||
static_assert(detail::is_expected<Ret>::value, "F must return an expected");
|
|
||||||
|
|
||||||
return exp.has_value()
|
|
||||||
? detail::invoke(std::forward<F>(f), *std::forward<Exp>(exp))
|
|
||||||
: Ret(unexpect, 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<exp_t<Exp>>::value> * = nullptr>
|
|
||||||
constexpr auto and_then_impl(Exp &&exp, F &&f) -> Ret {
|
|
||||||
static_assert(detail::is_expected<Ret>::value, "F must return an expected");
|
|
||||||
|
|
||||||
return exp.has_value() ? detail::invoke(std::forward<F>(f))
|
|
||||||
: Ret(unexpect, exp.error());
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef TL_EXPECTED_CXX14
|
|
||||||
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 expected_map_impl(Exp &&exp, F &&f) {
|
|
||||||
using result = ret_t<Exp, detail::decay_t<Ret>>;
|
|
||||||
return exp.has_value() ? result(detail::invoke(std::forward<F>(f),
|
|
||||||
*std::forward<Exp>(exp)))
|
|
||||||
: result(unexpect, 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 expected_map_impl(Exp &&exp, F &&f) {
|
|
||||||
using result = expected<void, err_t<Exp>>;
|
|
||||||
if (exp.has_value()) {
|
|
||||||
detail::invoke(std::forward<F>(f), *std::forward<Exp>(exp));
|
|
||||||
return result();
|
|
||||||
}
|
|
||||||
|
|
||||||
return result(unexpect, std::forward<Exp>(exp).error());
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
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 expected_map_impl(Exp &&exp, F &&f)
|
|
||||||
-> ret_t<Exp, detail::decay_t<Ret>> {
|
|
||||||
using result = ret_t<Exp, detail::decay_t<Ret>>;
|
|
||||||
|
|
||||||
return exp.has_value() ? result(detail::invoke(std::forward<F>(f),
|
|
||||||
*std::forward<Exp>(exp)))
|
|
||||||
: result(unexpect, 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 expected_map_impl(Exp &&exp, F &&f) -> expected<void, err_t<Exp>> {
|
|
||||||
if (exp.has_value()) {
|
|
||||||
detail::invoke(std::forward<F>(f), *std::forward<Exp>(exp));
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
return unexpected<err_t<Exp>>(std::forward<Exp>(exp).error());
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(TL_EXPECTED_CXX14) && !defined(TL_EXPECTED_GCC49) && \
|
|
||||||
!defined(TL_EXPECTED_GCC54)
|
|
||||||
template <class Exp, class F,
|
|
||||||
class Ret = decltype(detail::invoke(std::declval<F>(),
|
|
||||||
std::declval<Exp>().error())),
|
|
||||||
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>, detail::decay_t<Ret>>;
|
|
||||||
return exp.has_value()
|
|
||||||
? result(*std::forward<Exp>(exp))
|
|
||||||
: result(unexpect, detail::invoke(std::forward<F>(f),
|
|
||||||
std::forward<Exp>(exp).error()));
|
|
||||||
}
|
|
||||||
template <class Exp, class F,
|
|
||||||
class Ret = decltype(detail::invoke(std::declval<F>(),
|
|
||||||
std::declval<Exp>().error())),
|
|
||||||
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
|
|
||||||
template <class Exp, class F,
|
|
||||||
class Ret = decltype(detail::invoke(std::declval<F>(),
|
|
||||||
std::declval<Exp>().error())),
|
|
||||||
detail::enable_if_t<!std::is_void<Ret>::value> * = nullptr>
|
|
||||||
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()
|
|
||||||
? result(*std::forward<Exp>(exp))
|
|
||||||
: result(unexpect, detail::invoke(std::forward<F>(f),
|
|
||||||
std::forward<Exp>(exp).error()));
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class Exp, class F,
|
|
||||||
class Ret = decltype(detail::invoke(std::declval<F>(),
|
|
||||||
std::declval<Exp>().error())),
|
|
||||||
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
|
|
||||||
|
|
||||||
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 detail::decay_t<Exp> or_else_impl(Exp &&exp, F &&f) {
|
|
||||||
if (exp.has_value()) {
|
|
||||||
return std::forward<Exp>(exp);
|
|
||||||
}
|
|
||||||
|
|
||||||
return detail::invoke(std::forward<F>(f), *std::forward<Exp>(exp));
|
|
||||||
}
|
|
||||||
|
|
||||||
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>
|
|
||||||
detail::decay_t<Exp> or_else_impl(Exp &&exp, F &&f) {
|
|
||||||
if (exp.has_value()) {
|
|
||||||
return std::forward<Exp>(exp);
|
|
||||||
}
|
|
||||||
|
|
||||||
detail::invoke(std::forward<F>(f), *std::forward<Exp>(exp));
|
|
||||||
return std::forward<Exp>(exp);
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace detail
|
|
||||||
|
|
||||||
template <class T, class E, class U, class F>
|
template <class T, class E, class U, class F>
|
||||||
constexpr bool operator==(const expected<T, E> &lhs,
|
constexpr bool operator==(const expected<T, E> &lhs,
|
||||||
const expected<U, F> &rhs) {
|
const expected<U, F> &rhs) {
|
||||||
|
Reference in New Issue
Block a user