enum_name
Loading...
Searching...
No Matches
optional.hpp
1/*
2MIT License
3
4Copyright (c) 2024 mguludag
5
6Permission is hereby granted, free of charge, to any person obtaining a copy
7of this software and associated documentation files (the "Software"), to deal
8in the Software without restriction, including without limitation the rights
9to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10copies of the Software, and to permit persons to whom the Software is
11furnished to do so, subject to the following conditions:
12
13The above copyright notice and this permission notice shall be included in all
14copies or substantial portions of the Software.
15
16THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22SOFTWARE.
23*/
24
25#ifndef DETAIL_OPTIONAL_HPP
26#define DETAIL_OPTIONAL_HPP
27
29#include "mgutility/reflection/detail/meta.hpp"
30
31#include <exception>
32
33#if MGUTILITY_CPLUSPLUS >= 201703L
34#include <optional>
35#endif
36
37namespace mgutility {
38
39#if MGUTILITY_CPLUSPLUS < 201703L
40
44struct bad_optional_access : public std::exception {
50 const char *what() const noexcept { return "optional has no value"; }
51};
52
53struct nullopt_t;
54
60template <typename T> class optional {
61public:
65 MGUTILITY_CNSTXPR inline optional(nullopt_t &)
66 : dummy_{0}, has_value_{false} {}
67
71 MGUTILITY_CNSTXPR inline optional() : dummy_{0}, has_value_{false} {}
72
79 template <typename... Args>
80 MGUTILITY_CNSTXPR inline optional(Args &&...args)
81 : value_{T{std::forward<Args>(args)...}}, has_value_{true} {}
82
88 MGUTILITY_CNSTXPR inline optional(T &&value)
89 : value_{value}, has_value_{true} {}
90
96 MGUTILITY_CNSTXPR inline optional(const optional &other)
97 : value_{other.value_}, has_value_{other.has_value_} {}
98
104 MGUTILITY_CNSTXPR inline optional(optional &&other)
105 : value_{other.value_}, has_value_{other.has_value_} {
106 other.reset();
107 }
108
112 inline ~optional() { has_value_ = false; }
113
120 MGUTILITY_CNSTXPR inline optional &operator=(const optional &other) {
121 value_ = other.value_;
122 has_value_ = other.has_value_;
123 return *this;
124 }
125
132 MGUTILITY_CNSTXPR inline optional &operator=(optional &&other) {
133 value_ = other.value_;
134 has_value_ = other.has_value_;
135 other.reset();
136 return *this;
137 }
138
144 MGUTILITY_CNSTXPR inline void swap(optional &&other) {
145 auto val = std::move(other.value_);
146 other.value_ = std::move(value_);
147 value_ = std::move(val);
148
149 auto hval = std::move(other.has_value_);
150 other.has_value_ = std::move(has_value_);
151 has_value_ = std::move(hval);
152 }
153
159 MGUTILITY_CNSTXPR inline T &operator*() { return value_; }
160
166 MGUTILITY_CNSTXPR inline T &operator*() const { return value_; }
167
174 MGUTILITY_CNSTXPR inline T &value() {
175 if (!has_value_)
176 throw bad_optional_access();
177 return value_;
178 }
179
186 MGUTILITY_CNSTXPR inline T &value() const {
187 if (!has_value_)
188 throw bad_optional_access();
189 return value_;
190 }
191
198 MGUTILITY_CNSTXPR inline T value_or(T &&value) {
199 return has_value_ ? value_ : value;
200 }
201
209 MGUTILITY_CNSTXPR inline T value_or(T &&value) const {
210 return has_value_ ? value_ : value;
211 }
212
219 MGUTILITY_CNSTXPR inline T value_or(const T &value) {
220 return has_value_ ? value_ : value;
221 }
222
230 MGUTILITY_CNSTXPR inline T value_or(const T &value) const {
231 return has_value_ ? value_ : value;
232 }
233
239 MGUTILITY_CNSTXPR inline void emplace(T value) {
240 value_ = std::move(value);
241 has_value_ = true;
242 }
243
250 template <typename... Args>
251 MGUTILITY_CNSTXPR inline void emplace(Args &&...args) {
252 value_ = std::move(T{std::forward<Args>(args)...});
253 has_value_ = true;
254 }
255
261 MGUTILITY_CNSTXPR inline bool has_value() const { return has_value_; }
262
266 template <typename U = T,
267 detail::enable_if_t<!std::is_destructible<U>::value, bool> = true>
268 MGUTILITY_CNSTXPR inline void reset() {
269 value_ = T{};
270 has_value_ = false;
271 }
272
276 template <typename U = T,
277 detail::enable_if_t<std::is_destructible<T>::value, bool> = true>
278 MGUTILITY_CNSTXPR inline void reset() {
279 value_.~T();
280 has_value_ = false;
281 }
282
288 MGUTILITY_CNSTXPR operator bool() { return has_value_; }
289
290private:
291 union {
292 T value_;
293 char dummy_[sizeof(T)];
294 };
295 bool has_value_;
296};
297
301struct nullopt_t {
308 template <typename T> MGUTILITY_CNSTXPR operator optional<T>() {
309 return optional<T>{};
310 }
311};
312
317
318#else
324template <typename T> using optional = std::optional<T>;
325
329inline constexpr auto nullopt{std::nullopt};
330
331#endif
332} // namespace mgutility
333
334#endif // DETAIL_OPTIONAL_HPP
A class template that provides optional (nullable) objects.
Definition optional.hpp:60
MGUTILITY_CNSTXPR optional & operator=(optional &&other)
Move assignment operator.
Definition optional.hpp:132
MGUTILITY_CNSTXPR T value_or(T &&value) const
Returns the stored value or a default value if empty (const version).
Definition optional.hpp:209
MGUTILITY_CNSTXPR void emplace(Args &&...args)
Constructs the value in-place with arguments.
Definition optional.hpp:251
MGUTILITY_CNSTXPR optional(Args &&...args)
Constructs an optional with a value.
Definition optional.hpp:80
~optional()
Destructor.
Definition optional.hpp:112
MGUTILITY_CNSTXPR optional & operator=(const optional &other)
Copy assignment operator.
Definition optional.hpp:120
MGUTILITY_CNSTXPR optional(T &&value)
Constructs an optional with a value.
Definition optional.hpp:88
MGUTILITY_CNSTXPR bool has_value() const
Checks if the optional has a value.
Definition optional.hpp:261
MGUTILITY_CNSTXPR T & operator*() const
Dereferences the stored value (const version).
Definition optional.hpp:166
MGUTILITY_CNSTXPR optional()
Constructs an empty optional.
Definition optional.hpp:71
MGUTILITY_CNSTXPR optional(optional &&other)
Move constructor.
Definition optional.hpp:104
MGUTILITY_CNSTXPR T & operator*()
Dereferences the stored value.
Definition optional.hpp:159
MGUTILITY_CNSTXPR optional(const optional &other)
Copy constructor.
Definition optional.hpp:96
MGUTILITY_CNSTXPR void reset()
Resets the optional, making it empty.
Definition optional.hpp:268
MGUTILITY_CNSTXPR optional(nullopt_t &)
Constructs an empty optional.
Definition optional.hpp:65
MGUTILITY_CNSTXPR void emplace(T value)
Constructs the value in-place.
Definition optional.hpp:239
MGUTILITY_CNSTXPR T & value() const
Accesses the stored value (const version).
Definition optional.hpp:186
MGUTILITY_CNSTXPR T & value()
Accesses the stored value.
Definition optional.hpp:174
MGUTILITY_CNSTXPR void swap(optional &&other)
Swaps the contents of this optional with another.
Definition optional.hpp:144
MGUTILITY_CNSTXPR T value_or(T &&value)
Returns the stored value or a default value if empty.
Definition optional.hpp:198
MGUTILITY_CNSTXPR T value_or(const T &value) const
Returns the stored value or a default value if empty (const version).
Definition optional.hpp:230
MGUTILITY_CNSTXPR T value_or(const T &value)
Returns the stored value or a default value if empty.
Definition optional.hpp:219
Defines macros for compiler and standard support detection.
Checks for MSVC compiler version.
Definition enum_for_each.hpp:34
auto nullopt
A global instance of nullopt_t to represent null optional.
Definition optional.hpp:316
Exception thrown when accessing an empty optional.
Definition optional.hpp:44
const char * what() const noexcept
Returns the exception message.
Definition optional.hpp:50
Represents a null optional.
Definition optional.hpp:301