libQuotient
A Qt library for building matrix clients
expected.h
Go to the documentation of this file.
1 // SPDX-FileCopyrightText: 2022 Kitsune Ral <Kitsune-Ral@users.sf.net>
2 // SPDX-License-Identifier: LGPL-2.1-or-later
3 
4 #pragma once
5 
6 #include <variant>
7 #include "util.h"
8 
9 namespace Quotient {
10 
11 //! \brief A minimal subset of std::expected from C++23
12 template <typename T, typename E>
13  requires (!std::is_same_v<T, E>)
14 class Expected {
15 private:
16  template <typename X>
17  static constexpr auto is_constructible_v =
18  std::is_constructible_v<T, X> || std::is_constructible_v<E, X>;
19 
20 public:
21  using value_type = T;
22  using error_type = E;
23 
24  Expected() = default;
25  Expected(const Expected&) = default;
26  Expected(Expected&&) noexcept = default;
27  ~Expected() = default;
28 
29  template <typename X>
30  requires is_constructible_v<X>
31  QUO_IMPLICIT Expected(X&& x) // NOLINT(google-explicit-constructor)
32  : data(std::forward<X>(x))
33  {}
34 
35  Expected& operator=(const Expected&) = default;
36  Expected& operator=(Expected&&) noexcept = default;
37 
38  template <typename X>
39  requires is_constructible_v<X>
40  Expected& operator=(X&& x)
41  {
42  data = std::forward<X>(x);
43  return *this;
44  }
45 
46  bool has_value() const { return std::holds_alternative<T>(data); }
47  explicit operator bool() const { return has_value(); }
48 
49  const value_type& value() const& { return std::get<T>(data); }
50  value_type& value() & { return std::get<T>(data); }
51  value_type value() && { return std::get<T>(std::move(data)); }
52 
53  const value_type& operator*() const& { return value(); }
54  value_type& operator*() & { return value(); }
55 
56  const value_type* operator->() const& { return std::get_if<T>(&data); }
57  value_type* operator->() & { return std::get_if<T>(&data); }
58 
59  template <class U>
60  const T& value_or(const U& fallback) const&
61  {
62  if (has_value())
63  return value();
64  return fallback;
65  }
66  template <class U>
67  T&& value_or(U&& fallback) &&
68  {
69  if (has_value())
70  return std::move(value());
71  return std::forward<U>(fallback);
72  }
73 
74  T&& move_value_or(T&& fallback)
75  {
76  if (has_value())
77  return std::move(value());
78  return std::move(fallback);
79  }
80 
81  const E& error() const& { return std::get<E>(data); }
82  E& error() & { return std::get<E>(data); }
83 
84 private:
85  std::variant<T, E> data;
86 };
87 
88 } // namespace Quotient