xtd 0.2.0
Loading...
Searching...
No Matches
optional.h
Go to the documentation of this file.
1
3#pragma once
5#if defined(__cpp_lib_optional) || __cplusplus >= 201703l
6#include <optional>
7#else
8#include <stdexcept>
9#include <utility>
10
11namespace std {
12 /*
13 class bad_optional_access : public std::exception {
14 public:
15 const char* what() const noexcept override {return "bad optional access";}
16 };
17 */
18
19 template <typename value_t>
20 class optional {
21 private:
22 alignas(value_t) unsigned char data_[sizeof(value_t)];
23 bool has_value_;
24
25 public:
26 optional() : has_value_(false) {}
27
28 optional(const value_t& value) : has_value_(true) {
29 new (data_) value_t(value);
30 }
31
32 optional(value_t&& value) : has_value_(true) {
33 new (data_) value_t(std::move(value));
34 }
35
36 optional(const optional& other) : has_value_(other.has_value_) {
37 if (other.has_value_) {
38 new (data_) value_t(*other);
39 }
40 }
41
42 optional(optional&& other) : has_value_(other.has_value_) {
43 if (other.has_value_) {
44 new (data_) value_t(std::move(*other));
45 }
46 other.reset();
47 }
48
49 optional& operator=(const value_t& value) {
50 if (has_value_) {
51 *reinterpret_cast<value_t*>(data_) = value;
52 } else {
53 new (data_) value_t(value);
54 has_value_ = true;
55 }
56 return *this;
57 }
58
59 optional& operator=(value_t&& value) {
60 if (has_value_) {
61 *reinterpret_cast<value_t*>(data_) = std::move(value);
62 } else {
63 new (data_) value_t(std::move(value));
64 has_value_ = true;
65 }
66 return *this;
67 }
68
69 optional& operator=(const optional& other) {
70 if (this == &other) {
71 return *this;
72 }
73
74 if (other.has_value_) {
75 if (has_value()) {
76 *reinterpret_cast<value_t*>(data_) = *other;
77 } else {
78 new (data_) value_t(*other);
79 has_value_ = true;
80 }
81 } else {
82 reset();
83 }
84 return *this;
85 }
86
87 optional& operator=(optional&& other) {
88 if (this == &other) {
89 return *this;
90 }
91
92 if (other.has_value_) {
93 if (has_value()) {
94 *reinterpret_cast<value_t*>(data_) = std::move(*other);
95 } else {
96 new (data_) value_t(std::move(*other));
97 has_value_ = true;
98 }
99 } else {
100 reset();
101 }
102 other.reset();
103 return *this;
104 }
105
106 ~optional() {
107 reset();
108 }
109
110 bool has_value() const {
111 return has_value_;
112 }
113
114 const value_t& value() const {
115 return operator*();
116 }
117
118 const value_t& value_or(const value_t& other) const {
119 return has_value() ? operator*() : other;
120 }
121
122 void reset() {
123 if (!has_value()) return;
124 reinterpret_cast<value_t*>(data_)->~value_t();
125 has_value_ = false;
126 }
127
128 const value_t* operator->() const {
129 if (!has_value()) {
130 throw std::runtime_error("optional does not contain a value.");
131 }
132 return reinterpret_cast<const value_t*>(data_);
133 }
134
135 value_t* operator->() {
136 if (!has_value_) {
137 throw std::runtime_error("optional does not contain a value.");
138 }
139 return reinterpret_cast<value_t*>(data_);
140 }
141
142 const value_t& operator*() const {
143 return *operator->();
144 }
145
146 value_t& operator*() {
147 return *operator->();
148 }
149
150 explicit operator bool() const {
151 return has_value_;
152 }
153 };
154}
155#endif
@ other
The operating system is other.