|
|
@@ -1,5 +1,7 @@
|
|
|
#pragma once
|
|
|
|
|
|
+#include <type_traits>
|
|
|
+
|
|
|
#ifdef __cpp_lib_expected
|
|
|
#if __cpp_lib_expected >= 202202L
|
|
|
#include <expected>
|
|
|
@@ -77,6 +79,12 @@ private:
|
|
|
};
|
|
|
|
|
|
template <typename T, typename E> class expected {
|
|
|
+public:
|
|
|
+ using value_type = T;
|
|
|
+ using error_type = E;
|
|
|
+ using unexpected_type = unexpected<E>;
|
|
|
+ template <typename U> using rebind = expected<U, error_type>;
|
|
|
+
|
|
|
public:
|
|
|
constexpr expected() = default;
|
|
|
|
|
|
@@ -84,9 +92,9 @@ public:
|
|
|
constexpr explicit(!std::is_convertible_v<const U &, T> && !std::is_convertible_v<const G &, E>)
|
|
|
expected(expected<U, G> const & other) {
|
|
|
if (other.has_value()) {
|
|
|
- *this = *other;
|
|
|
+ value_.template emplace<0>(*other);
|
|
|
} else {
|
|
|
- *this = other.error();
|
|
|
+ value_.template emplace<1>(other.error());
|
|
|
}
|
|
|
}
|
|
|
|
|
|
@@ -94,9 +102,9 @@ public:
|
|
|
constexpr explicit(!std::is_convertible_v<U, T> && !std::is_convertible_v<G, E>)
|
|
|
expected(expected<U, G> && other) {
|
|
|
if (other.has_value()) {
|
|
|
- *this = *std::move(other);
|
|
|
+ value_.template emplace<0>(*std::move(other));
|
|
|
} else {
|
|
|
- *this = std::move(other).error();
|
|
|
+ value_.template emplace<1>(std::move(other).error());
|
|
|
}
|
|
|
}
|
|
|
|
|
|
@@ -112,6 +120,22 @@ public:
|
|
|
constexpr explicit(!std::is_convertible_v<G, E>) expected(unexpected<G> && e)
|
|
|
: value_(std::in_place_index<1>, std::move(e).error()) {}
|
|
|
|
|
|
+ template <typename... Args>
|
|
|
+ constexpr explicit expected(std::in_place_t, Args &&... args)
|
|
|
+ : value_(std::in_place_index<0>, std::forward<Args>(args)...) {}
|
|
|
+
|
|
|
+ template <typename U, typename... Args>
|
|
|
+ constexpr explicit expected(std::in_place_t, std::initializer_list<U> il, Args &&... args)
|
|
|
+ : value_(std::in_place_index<0>, il, std::forward<Args>(args)...) {}
|
|
|
+
|
|
|
+ template <typename... Args>
|
|
|
+ constexpr explicit expected(unexpect_t, Args &&... args)
|
|
|
+ : value_(std::in_place_index<1>, std::forward<Args>(args)...) {}
|
|
|
+
|
|
|
+ template <typename U, typename... Args>
|
|
|
+ constexpr explicit expected(unexpect_t, std::initializer_list<U> il, Args &&... args)
|
|
|
+ : value_(std::in_place_index<1>, il, std::forward<Args>(args)...) {}
|
|
|
+
|
|
|
constexpr explicit operator bool() const noexcept { return has_value(); }
|
|
|
constexpr bool has_value() const noexcept { return value_.index() == 0; }
|
|
|
|
|
|
@@ -152,6 +176,12 @@ private:
|
|
|
};
|
|
|
|
|
|
template <typename E> class expected<void, E> {
|
|
|
+public:
|
|
|
+ using value_type = void;
|
|
|
+ using error_type = E;
|
|
|
+ using unexpected_type = unexpected<E>;
|
|
|
+ template <typename U> using rebind = expected<U, error_type>;
|
|
|
+
|
|
|
public:
|
|
|
constexpr expected() = default;
|
|
|
|
|
|
@@ -178,6 +208,16 @@ public:
|
|
|
constexpr explicit(!std::is_convertible_v<G, E>) expected(unexpected<G> && e)
|
|
|
: value_(std::in_place_index<1>, std::move(e).error()) {}
|
|
|
|
|
|
+ constexpr explicit expected(std::in_place_t) {}
|
|
|
+
|
|
|
+ template <typename... Args>
|
|
|
+ constexpr explicit expected(unexpect_t, Args &&... args)
|
|
|
+ : value_(std::in_place, std::forward<Args>(args)...) {}
|
|
|
+
|
|
|
+ template <typename U, typename... Args>
|
|
|
+ constexpr explicit expected(unexpect_t, std::initializer_list<U> il, Args &&... args)
|
|
|
+ : value_(std::in_place, il, std::forward<Args>(args)...) {}
|
|
|
+
|
|
|
constexpr explicit operator bool() const noexcept { return has_value(); }
|
|
|
constexpr bool has_value() const noexcept { return not value_.has_value(); }
|
|
|
|