mirror of
https://github.com/mutouyun/cpp-ipc.git
synced 2025-12-06 16:56:45 +08:00
upd: [imp] improve expected
This commit is contained in:
parent
3b781db42e
commit
0883929918
@ -138,19 +138,12 @@ template <typename S, typename T, typename E>
|
|||||||
struct value_getter : data_union<T, E> {
|
struct value_getter : data_union<T, E> {
|
||||||
using data_union<T, E>::data_union;
|
using data_union<T, E>::data_union;
|
||||||
|
|
||||||
value_getter(S const &other) : data_union<T, E>(nullptr) {
|
template <typename U>
|
||||||
if (bool(static_cast<S &>(other))) {
|
value_getter(U &&other) : data_union<T, E>(nullptr) {
|
||||||
construct<data_union<T, E>>(this, in_place, other.value());
|
if (other) {
|
||||||
|
construct<data_union<T, E>>(this, in_place, std::forward<U>(other).value());
|
||||||
} else {
|
} else {
|
||||||
construct<data_union<T, E>>(this, unexpected, other.error());
|
construct<data_union<T, E>>(this, unexpected, std::forward<U>(other).error());
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
value_getter(S &&other) : data_union<T, E>(nullptr) {
|
|
||||||
if (bool(static_cast<S &>(other))) {
|
|
||||||
construct<data_union<T, E>>(this, in_place, std::move(other).value());
|
|
||||||
} else {
|
|
||||||
construct<data_union<T, E>>(this, unexpected, std::move(other).error());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -198,19 +191,12 @@ template <typename S, typename E>
|
|||||||
struct value_getter<S, void, E> : data_union<void, E> {
|
struct value_getter<S, void, E> : data_union<void, E> {
|
||||||
using data_union<void, E>::data_union;
|
using data_union<void, E>::data_union;
|
||||||
|
|
||||||
value_getter(S const &other) : data_union<T, E>(nullptr) {
|
template <typename U>
|
||||||
if (bool(static_cast<S &>(other))) {
|
value_getter(U &&other) : data_union<T, E>(nullptr) {
|
||||||
|
if (other) {
|
||||||
construct<data_union<T, E>>(this, in_place);
|
construct<data_union<T, E>>(this, in_place);
|
||||||
} else {
|
} else {
|
||||||
construct<data_union<T, E>>(this, unexpected, other.error());
|
construct<data_union<T, E>>(this, unexpected, std::forward<U>(other).error());
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
value_getter(S &&other) : data_union<T, E>(nullptr) {
|
|
||||||
if (bool(static_cast<S &>(other))) {
|
|
||||||
construct<data_union<T, E>>(this, in_place);
|
|
||||||
} else {
|
|
||||||
construct<data_union<T, E>>(this, unexpected, std::move(other).error());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -235,6 +221,9 @@ struct value_getter<S, void, E> : data_union<void, E> {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Define the expected storage.
|
||||||
|
*/
|
||||||
template <typename T, typename E>
|
template <typename T, typename E>
|
||||||
struct storage : value_getter<storage<T, E>, T, E> {
|
struct storage : value_getter<storage<T, E>, T, E> {
|
||||||
using getter_t = value_getter<storage<T, E>, T, E>;
|
using getter_t = value_getter<storage<T, E>, T, E>;
|
||||||
@ -259,6 +248,16 @@ struct storage : value_getter<storage<T, E>, T, E> {
|
|||||||
: getter_t(std::move(other))
|
: getter_t(std::move(other))
|
||||||
, has_value_(std::exchange(other.has_value_, false)) {}
|
, has_value_(std::exchange(other.has_value_, false)) {}
|
||||||
|
|
||||||
|
template <typename T_, typename E_>
|
||||||
|
storage(storage<T_, E_> const &other)
|
||||||
|
: getter_t(other)
|
||||||
|
, has_value_(other.has_value_) {}
|
||||||
|
|
||||||
|
template <typename T_, typename E_>
|
||||||
|
storage(storage<T_, E_> &&other)
|
||||||
|
: getter_t(std::move(other))
|
||||||
|
, has_value_(std::exchange(other.has_value_, false)) {}
|
||||||
|
|
||||||
bool has_value() const noexcept {
|
bool has_value() const noexcept {
|
||||||
return has_value_;
|
return has_value_;
|
||||||
}
|
}
|
||||||
@ -315,4 +314,79 @@ R or_else(E &&exp, F &&f) {
|
|||||||
|
|
||||||
} // namespace detail_expected
|
} // namespace detail_expected
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \class template <typename T, typename E> expected
|
||||||
|
* \brief Provides a way to store either of two values.
|
||||||
|
*/
|
||||||
|
template <typename T, typename E>
|
||||||
|
class expected : public detail_expected::storage<typename std::remove_cv<T>::type, E> {
|
||||||
|
public:
|
||||||
|
using value_type = typename std::remove_cv<T>::type;
|
||||||
|
using error_type = E;
|
||||||
|
|
||||||
|
using detail_expected::storage<value_type, E>::storage;
|
||||||
|
|
||||||
|
expected(expected const &) = default;
|
||||||
|
expected(expected &&) = default;
|
||||||
|
|
||||||
|
expected()
|
||||||
|
: detail_expected::storage<value_type, E>(in_place) {}
|
||||||
|
|
||||||
|
expected &operator=(expected other) {
|
||||||
|
this->swap(other);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Monadic operations
|
||||||
|
|
||||||
|
template <typename F>
|
||||||
|
auto and_then(F &&f) & {
|
||||||
|
return detail_expected::and_then(*this, std::forward<F>(f));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename F>
|
||||||
|
auto and_then(F &&f) const & {
|
||||||
|
return detail_expected::and_then(*this, std::forward<F>(f));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename F>
|
||||||
|
auto and_then(F &&f) && {
|
||||||
|
return detail_expected::and_then(std::move(*this), std::forward<F>(f));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename F>
|
||||||
|
auto or_else(F &&f) & {
|
||||||
|
return detail_expected::or_else(*this, std::forward<F>(f));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename F>
|
||||||
|
auto or_else(F &&f) const & {
|
||||||
|
return detail_expected::or_else(*this, std::forward<F>(f));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename F>
|
||||||
|
auto or_else(F &&f) && {
|
||||||
|
return detail_expected::or_else(std::move(*this), std::forward<F>(f));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Compares
|
||||||
|
|
||||||
|
template <typename T1, typename E1, typename T2, typename E2>
|
||||||
|
bool operator==(expected<T1, E1> const &lhs, expected<T2, E2> const &rhs) {
|
||||||
|
return (lhs.has_value() == rhs.has_value())
|
||||||
|
&& (lhs.has_value() ? *lhs == *rhs : lhs.error() == rhs.error());
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename E1, typename E2>
|
||||||
|
bool operator==(expected<void, E1> const &lhs, expected<void, E2> const &rhs) {
|
||||||
|
return (lhs.has_value() == rhs.has_value())
|
||||||
|
&& (lhs.has_value() || lhs.error() == rhs.error());
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T1, typename E1, typename T2, typename E2>
|
||||||
|
bool operator!=(expected<T1, E1> const &lhs, expected<T2, E2> const &rhs) {
|
||||||
|
return !(lhs == rhs);
|
||||||
|
}
|
||||||
|
|
||||||
LIBIMP_NAMESPACE_END_
|
LIBIMP_NAMESPACE_END_
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user