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  Q_IMPLICIT Expected(X&& x) : data(std::forward<X>(x))
32  {}
33 
34  Expected& operator=(const Expected&) = default;
35  Expected& operator=(Expected&&) noexcept = default;
36 
37  template <typename X>
38  requires is_constructible_v<X>
39  Expected& operator=(X&& x)
40  {
41  data = std::forward<X>(x);
42  return *this;
43  }
44 
45  bool has_value() const { return std::holds_alternative<T>(data); }
46  explicit operator bool() const { return has_value(); }
47 
48  const value_type& value() const& { return std::get<T>(data); }
49  value_type& value() & { return std::get<T>(data); }
50  value_type value() && { return std::get<T>(std::move(data)); }
51 
52  const value_type& operator*() const& { return value(); }
53  value_type& operator*() & { return value(); }
54 
55  const value_type* operator->() const& { return std::get_if<T>(&data); }
56  value_type* operator->() & { return std::get_if<T>(&data); }
57 
58  template <class U>
59  const T& value_or(const U& fallback) const&
60  {
61  if (has_value())
62  return value();
63  return fallback;
64  }
65  template <class U>
66  T&& value_or(U&& fallback) &&
67  {
68  if (has_value())
69  return std::move(value());
70  return std::forward<U>(fallback);
71  }
72 
73  T&& move_value_or(T&& fallback)
74  {
75  if (has_value())
76  return std::move(value());
77  return std::move(fallback);
78  }
79 
80  const E& error() const& { return std::get<E>(data); }
81  E& error() & { return std::get<E>(data); }
82 
83 private:
84  std::variant<T, E> data;
85 };
86 
87 } // namespace Quotient