MT Core (C++)
Core library for replacing C++ standard in project usage
Loading...
Searching...
No Matches
optional.hpp
Go to the documentation of this file.
1/*
2
3Copyright 2025 Matthew Tolman
4
5Licensed under the Apache License, Version 2.0 (the "License");
6you may not use this file except in compliance with the License.
7You may obtain a copy of the License at
8
9 http://www.apache.org/licenses/LICENSE-2.0
10
11Unless required by applicable law or agreed to in writing, software
12distributed under the License is distributed on an "AS IS" BASIS,
13WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14See the License for the specific language governing permissions and
15limitations under the License.
16
17*/
18
19#ifndef MTCORE_OPTIONAL_HPP
20#define MTCORE_OPTIONAL_HPP
21
22#include "../core.hpp"
23#include "../traits.hpp"
24
25#include <memory>
26#include <ostream>
27#include <variant>
28
29namespace mtcore {
30
38 template<typename T>
39 struct Optional;
40
47 template<typename T>
48 struct Optional<T *> {
49 private:
50 T *v;
51
52 public:
56 Optional() : v(nullptr) {}
57
61 Optional(T *value) : v(value) {}
62
66 bool operator==(const Optional &other) const noexcept {
67 if (v == nullptr) {
68 return other.v == nullptr;
69 }
70 if (other.v == nullptr) {
71 return false;
72 }
73
74 ensure(v && other.v, "EXISTS CHECK FAILED");
75 return v == other.v;
76 }
77
81 [[nodiscard]] bool has_value() const noexcept { return v != nullptr; }
82
87 [[nodiscard]] T value_or(const T &def) const noexcept {
88 if (has_value()) {
89 return value();
90 }
91 return def;
92 }
93
94 [[nodiscard]] T &value() noexcept {
95 ensure(has_value(), "CANNOT GET VALUE WHEN OPTIONAL IS EMPTY");
96 return *v;
97 }
98
99 [[nodiscard]] const T &value() const noexcept {
100 ensure(has_value(), "CANNOT GET VALUE WHEN OPTIONAL IS EMPTY");
101 return *v;
102 }
103
120 [[nodiscard]] bool copy_if_present(T *&out) const noexcept {
121 if (has_value()) {
122 out = v;
123 }
124 return has_value();
125 }
126
143 [[nodiscard]] bool copy_if_present(std::remove_const_t<T> &out) const noexcept {
144 if (has_value()) {
145 out = *v;
146 }
147 return has_value();
148 }
149
167 [[nodiscard]] bool move_if_present(std::remove_const_t<T> *&out) noexcept {
168 mtdefer { v = nullptr; };
169 if (has_value()) {
170 out = std::move(v);
171 return true;
172 }
173 return false;
174 }
175
193 [[nodiscard]] bool move_if_present(std::remove_const_t<T> &out) noexcept {
194 if (has_value()) {
195 out = std::move(*v);
196 }
197 mtdefer { v = nullptr; };
198 return has_value();
199 }
200
204 const T &operator*() const {
205 ensure(has_value(), "CANNNOT DERERFERENCE NULL OPTIONAL");
206 return *v;
207 }
208
212 const T *operator->() const {
213 ensure(has_value(), "CANNNOT DERERFERENCE NULL OPTIONAL");
214 return v;
215 }
216
221 ensure(has_value(), "CANNNOT DERERFERENCE NULL OPTIONAL");
222 return *v;
223 }
224
229 ensure(has_value(), "CANNNOT DERERFERENCE NULL OPTIONAL");
230 return v;
231 }
232 };
233
234 template<typename T>
235 struct Optional {
236 private:
237 std::variant<std::monostate, T> v;
238
239 public:
243 Optional() : v(std::monostate{}) { ensure(!has_value()); }
244
248 Optional(const T &value) : v(value) {}
249
253 Optional(T &&value) : v(std::forward<T>(value)) {}
254
258 bool operator==(const Optional &other) const noexcept {
259 if (has_value() != other.has_value()) {
260 return false;
261 }
262 if (!has_value()) {
263 return true;
264 }
265
266 ensure(has_value() && other.has_value(), "EXISTS CHECK FAILED");
267 return std::get<T>(v) == std::get<T>(other.v);
268 }
269
273 bool operator==(const T &other) const noexcept {
274 if (!has_value()) {
275 return false;
276 }
277 return std::get<T>(v) == other;
278 }
279
284 [[nodiscard]] T value_or(const T &def) const noexcept {
285 if (has_value()) {
286 return value();
287 }
288 return def;
289 }
290
294 [[nodiscard]] bool has_value() const noexcept { return std::holds_alternative<T>(v); }
295
299 [[nodiscard]] bool empty() const noexcept { return std::holds_alternative<std::monostate>(v); }
300
301 [[nodiscard]] T &value() noexcept {
302 ensure(has_value(), "CANNOT GET VALUE WHEN OPTIONAL IS EMPTY");
303 return std::get<T>(v);
304 }
305
306 [[nodiscard]] const T &value() const noexcept {
307 ensure(has_value(), "CANNOT GET VALUE WHEN OPTIONAL IS EMPTY");
308 return std::get<T>(v);
309 }
310
327 [[nodiscard]] bool copy_if_present(std::remove_const_t<T> &out) const noexcept {
328 if (has_value()) {
329 out = std::get<T>(v);
330 return true;
331 }
332 return false;
333 }
334
352 [[nodiscard]] bool move_if_present(T &out) noexcept {
353 if (has_value()) {
354 out = std::move(std::get<T>(v));
355 v = std::monostate{};
356 return true;
357 }
358 return false;
359 }
360
364 const T &operator*() const {
365 ensure(has_value(), "CANNNOT DERERFERENCE NULL OPTIONAL");
366 return std::get<T>(v);
367 }
368
372 const T *operator->() const {
373 ensure(has_value(), "CANNNOT DERERFERENCE NULL OPTIONAL");
374 return &std::get<T>(v);
375 }
376
381 ensure(has_value(), "CANNNOT DERERFERENCE NULL OPTIONAL");
382 return std::get<T>(v);
383 }
384
389 ensure(has_value(), "CANNNOT DERERFERENCE NULL OPTIONAL");
390 return &std::get<T>(v);
391 }
392 };
393
398 struct Nullopt {
399 template<typename T>
400 operator Optional<T>() const {
401 return Optional<T>{};
402 }
403 };
404
409 constexpr auto nullopt = Nullopt{};
410} // namespace mtcore
411
412
413#endif // MTCORE_OPTIONAL_HPP
constexpr auto nullopt
Placeholder value for an empty Optional.
Definition optional.hpp:409
#define ensure(check,...)
Ensures that a check holds true, aborts the program if not true Will print error if the condition is ...
#define mtdefer
Defer statement that will mtdefer execution until the scope is left, at which point the code will run...
Core library for C++ with Zig-related functionality.
Placeholder value for any empty Optional (similar to std::nullopt)
Definition optional.hpp:398
const T & value() const noexcept
Definition optional.hpp:99
bool copy_if_present(T *&out) const noexcept
Copies a value to a reference output destination if a value is present Designed to be used by simple ...
Definition optional.hpp:120
const T * operator->() const
Dereferences the internal value.
Definition optional.hpp:212
T value_or(const T &def) const noexcept
Returns the value in the optional, or a default value if the optional is empty.
Definition optional.hpp:87
Optional()
Creates an empty Optional.
Definition optional.hpp:56
bool has_value() const noexcept
Definition optional.hpp:81
bool operator==(const Optional &other) const noexcept
Checks if value is equal to another Optional.
Definition optional.hpp:66
Optional(T *value)
Creates an Optional from a value.
Definition optional.hpp:61
T * operator->()
Dereferences the internal value.
Definition optional.hpp:228
const T & operator*() const
Dereferences the internal value.
Definition optional.hpp:204
bool move_if_present(std::remove_const_t< T > *&out) noexcept
Moves a value to a reference output destination if a value is present.
Definition optional.hpp:167
T & operator*()
Dereferences the internal value.
Definition optional.hpp:220
bool copy_if_present(std::remove_const_t< T > &out) const noexcept
Copies a value to a reference output destination if a value is present Designed to be used by simple ...
Definition optional.hpp:143
T & value() noexcept
Definition optional.hpp:94
bool move_if_present(std::remove_const_t< T > &out) noexcept
Moves a value to a reference output destination if a value is present.
Definition optional.hpp:193
Represents a value that may or may not exist (an "Optional" value) Similar concept to std::optional,...
Definition optional.hpp:235
bool operator==(const Optional &other) const noexcept
Checks if value is equal to another Optional.
Definition optional.hpp:258
Optional(const T &value)
Creates an Optional from a value.
Definition optional.hpp:248
const T * operator->() const
Dereferences the internal value.
Definition optional.hpp:372
bool has_value() const noexcept
Definition optional.hpp:294
T * operator->()
Dereferences the internal value.
Definition optional.hpp:388
Optional(T &&value)
Creates an Optional from a value.
Definition optional.hpp:253
T & value() noexcept
Definition optional.hpp:301
bool operator==(const T &other) const noexcept
Checks if value is equal to a non-Optional value.
Definition optional.hpp:273
const T & value() const noexcept
Definition optional.hpp:306
const T & operator*() const
Dereferences the internal value.
Definition optional.hpp:364
Optional()
Creates an empty Optional.
Definition optional.hpp:243
T & operator*()
Dereferences the internal value.
Definition optional.hpp:380
T value_or(const T &def) const noexcept
Returns the value in the optional, or a default value if the optional is empty.
Definition optional.hpp:284
bool empty() const noexcept
Definition optional.hpp:299
bool move_if_present(T &out) noexcept
Moves a value to a reference output destination if a value is present.
Definition optional.hpp:352
bool copy_if_present(std::remove_const_t< T > &out) const noexcept
Copies a value to a reference output destination if a value is present Designed to be used by simple ...
Definition optional.hpp:327