libpromeki 1.0.0-alpha
PROfessional MEdia toolKIt
 
Loading...
Searching...
No Matches
optional.h
Go to the documentation of this file.
1
8#pragma once
9
10
11#include <promeki/config.h>
12#if PROMEKI_ENABLE_CORE
13#include <optional>
14#include <type_traits>
15#include <utility>
16#include <promeki/namespace.h>
17
18PROMEKI_NAMESPACE_BEGIN
19
49template <typename T> class Optional {
50 public:
52 using ValueType = T;
53
55 using DataType = std::optional<T>;
56
58 Optional() = default;
59
61 Optional(std::nullopt_t) noexcept {}
62
67 Optional(const T &value) : d(value) {}
68
73 Optional(T &&value) noexcept(std::is_nothrow_move_constructible_v<T>) : d(std::move(value)) {}
74
79 Optional(const DataType &other) : d(other) {}
80
85 Optional(DataType &&other) noexcept(std::is_nothrow_move_constructible_v<T>) : d(std::move(other)) {}
86
88 Optional(const Optional &other) = default;
89
91 Optional(Optional &&other) noexcept(std::is_nothrow_move_constructible_v<T>) = default;
92
94 ~Optional() = default;
95
97 Optional &operator=(const Optional &other) = default;
98
100 Optional &operator=(Optional &&other) noexcept(std::is_nothrow_move_assignable_v<T>) = default;
101
103 Optional &operator=(std::nullopt_t) noexcept {
104 d.reset();
105 return *this;
106 }
107
118 template <typename U,
119 typename = std::enable_if_t<!std::is_same_v<std::decay_t<U>, Optional> &&
120 !std::is_same_v<std::decay_t<U>, std::nullopt_t> &&
121 std::is_constructible_v<T, U &&>>>
122 Optional &operator=(U &&value) {
123 d = std::forward<U>(value);
124 return *this;
125 }
126
131 bool hasValue() const noexcept { return d.has_value(); }
132
134 explicit operator bool() const noexcept { return d.has_value(); }
135
143 const T &value() const & { return d.value(); }
144
151 T &value() & { return d.value(); }
152
159 T &&value() && { return std::move(d).value(); }
160
166 template <typename U> T valueOr(U &&fallback) const & {
167 return d.value_or(std::forward<U>(fallback));
168 }
169
174 template <typename U> T valueOr(U &&fallback) && {
175 return std::move(d).value_or(std::forward<U>(fallback));
176 }
177
183 const T &operator*() const & noexcept { return *d; }
184
189 T &operator*() & noexcept { return *d; }
190
195 T &&operator*() && noexcept { return std::move(*d); }
196
202 const T *operator->() const noexcept { return d.operator->(); }
203
205 T *operator->() noexcept { return d.operator->(); }
206
208 void reset() noexcept { d.reset(); }
209
216 template <typename... ArgsT> T &emplace(ArgsT &&...args) {
217 return d.emplace(std::forward<ArgsT>(args)...);
218 }
219
221 void swap(Optional &other) noexcept(std::is_nothrow_swappable_v<T> &&
222 std::is_nothrow_move_constructible_v<T>) {
223 d.swap(other.d);
224 }
225
227 const DataType &toStdOptional() const noexcept { return d; }
228
230 DataType &toStdOptional() noexcept { return d; }
231
233 friend bool operator==(const Optional &lhs, const Optional &rhs) { return lhs.d == rhs.d; }
234
236 friend bool operator!=(const Optional &lhs, const Optional &rhs) { return lhs.d != rhs.d; }
237
239 friend bool operator==(const Optional &lhs, std::nullopt_t) noexcept { return !lhs.d.has_value(); }
240
242 friend bool operator==(std::nullopt_t, const Optional &rhs) noexcept { return !rhs.d.has_value(); }
243
245 friend bool operator!=(const Optional &lhs, std::nullopt_t) noexcept { return lhs.d.has_value(); }
246
248 friend bool operator!=(std::nullopt_t, const Optional &rhs) noexcept { return rhs.d.has_value(); }
249
250 private:
251 DataType d;
252};
253
254PROMEKI_NAMESPACE_END
255
256#endif // PROMEKI_ENABLE_CORE