From 9c8c33ab0b2138b45cbfe29f4be235f631730826 Mon Sep 17 00:00:00 2001 From: Alexey Rusakov Date: Mon, 16 May 2022 10:41:36 +0200 Subject: Expected<> This is a minimal implementation along the lines of `std::expected<>` introduced in C++23; once compilers catch up with C++23 support, it may become simply a typedef of std::expected. There are no tests as yet; but the following commits will introduce QOlmExpected that would replace the current `std::variant` pattern used throughout `QOlm*` classes, automatically pulling Expected under the coverage of `QOlm*` unit tests. --- lib/expected.h | 74 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 74 insertions(+) create mode 100644 lib/expected.h (limited to 'lib/expected.h') diff --git a/lib/expected.h b/lib/expected.h new file mode 100644 index 00000000..c8b8fd64 --- /dev/null +++ b/lib/expected.h @@ -0,0 +1,74 @@ +#pragma once + +#include + +namespace Quotient { + +//! \brief A minimal subset of std::expected from C++23 +template , bool> = true> +class Expected { +private: + template + using enable_if_constructible_t = std::enable_if_t< + std::is_constructible_v || std::is_constructible_v>; + +public: + using value_type = T; + using error_type = E; + + Expected() = default; + explicit Expected(const Expected&) = default; + explicit Expected(Expected&&) noexcept = default; + + template > + Expected(X&& x) + : data(std::forward(x)) + {} + + Expected& operator=(const Expected&) = default; + Expected& operator=(Expected&&) noexcept = default; + + template > + Expected& operator=(X&& x) + { + data = std::forward(x); + return *this; + } + + bool has_value() const { return std::holds_alternative(data); } + explicit operator bool() const { return has_value(); } + + const value_type& value() const& { return std::get(data); } + value_type& value() & { return std::get(data); } + value_type value() && { return std::get(std::move(data)); } + + const value_type& operator*() const& { return value(); } + value_type& operator*() & { return value(); } + + const value_type* operator->() const& { return std::get_if(&data); } + value_type* operator->() & { return std::get_if(&data); } + + template + T value_or(U&& fallback) const& + { + if (has_value()) + return value(); + return std::forward(fallback); + } + template + T value_or(U&& fallback) && + { + if (has_value()) + return value(); + return std::forward(fallback); + } + + const E& error() const& { return std::get(data); } + E& error() & { return std::get(data); } + +private: + std::variant data; +}; + +} // namespace Quotient -- cgit v1.2.3 From decc676f1e469dc26c80c33da64fad15805de8f2 Mon Sep 17 00:00:00 2001 From: Alexey Rusakov Date: Mon, 16 May 2022 17:35:58 +0200 Subject: expected.h: add a copyright notice [skip ci] --- lib/expected.h | 3 +++ 1 file changed, 3 insertions(+) (limited to 'lib/expected.h') diff --git a/lib/expected.h b/lib/expected.h index c8b8fd64..7b9e7f1d 100644 --- a/lib/expected.h +++ b/lib/expected.h @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: 2022 Kitsune Ral +// SPDX-License-Identifier: LGPL-2.1-or-later + #pragma once #include -- cgit v1.2.3