aboutsummaryrefslogtreecommitdiff
path: root/lib/expected.h
diff options
context:
space:
mode:
authorn-peugnet <n.peugnet@free.fr>2022-10-06 19:27:24 +0200
committern-peugnet <n.peugnet@free.fr>2022-10-06 19:27:24 +0200
commitd911b207f49e936b3e992200796110f0749ed150 (patch)
tree96d20ebb4d074a4c1755e21cb316a52d584daee3 /lib/expected.h
parent8ad8a74152c5701b6ca1f9a00487ba9257a439b4 (diff)
parent56c2f2e2b809b9077393eb617828f33d144f5634 (diff)
downloadlibquotient-d911b207f49e936b3e992200796110f0749ed150.tar.gz
libquotient-d911b207f49e936b3e992200796110f0749ed150.zip
New upstream version 0.7.0
Diffstat (limited to 'lib/expected.h')
-rw-r--r--lib/expected.h78
1 files changed, 78 insertions, 0 deletions
diff --git a/lib/expected.h b/lib/expected.h
new file mode 100644
index 00000000..81e186ea
--- /dev/null
+++ b/lib/expected.h
@@ -0,0 +1,78 @@
+// SPDX-FileCopyrightText: 2022 Kitsune Ral <Kitsune-Ral@users.sf.net>
+// SPDX-License-Identifier: LGPL-2.1-or-later
+
+#pragma once
+
+#include <variant>
+
+namespace Quotient {
+
+//! \brief A minimal subset of std::expected from C++23
+template <typename T, typename E,
+ std::enable_if_t<!std::is_same_v<T, E>, bool> = true>
+class Expected {
+private:
+ template <typename X>
+ using enable_if_constructible_t = std::enable_if_t<
+ std::is_constructible_v<T, X> || std::is_constructible_v<E, X>>;
+
+public:
+ using value_type = T;
+ using error_type = E;
+
+ Expected() = default;
+ Expected(const Expected&) = default;
+ Expected(Expected&&) noexcept = default;
+ ~Expected() = default;
+
+ template <typename X, typename = enable_if_constructible_t<X>>
+ QUO_IMPLICIT Expected(X&& x) // NOLINT(google-explicit-constructor)
+ : data(std::forward<X>(x))
+ {}
+
+ Expected& operator=(const Expected&) = default;
+ Expected& operator=(Expected&&) noexcept = default;
+
+ template <typename X, typename = enable_if_constructible_t<X>>
+ Expected& operator=(X&& x)
+ {
+ data = std::forward<X>(x);
+ return *this;
+ }
+
+ bool has_value() const { return std::holds_alternative<T>(data); }
+ explicit operator bool() const { return has_value(); }
+
+ const value_type& value() const& { return std::get<T>(data); }
+ value_type& value() & { return std::get<T>(data); }
+ value_type value() && { return std::get<T>(std::move(data)); }
+
+ const value_type& operator*() const& { return value(); }
+ value_type& operator*() & { return value(); }
+
+ const value_type* operator->() const& { return std::get_if<T>(&data); }
+ value_type* operator->() & { return std::get_if<T>(&data); }
+
+ template <class U>
+ T value_or(U&& fallback) const&
+ {
+ if (has_value())
+ return value();
+ return std::forward<U>(fallback);
+ }
+ template <class U>
+ T value_or(U&& fallback) &&
+ {
+ if (has_value())
+ return value();
+ return std::forward<U>(fallback);
+ }
+
+ const E& error() const& { return std::get<E>(data); }
+ E& error() & { return std::get<E>(data); }
+
+private:
+ std::variant<T, E> data;
+};
+
+} // namespace Quotient