Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Kitware
GitHub Repository: Kitware/CMake
Path: blob/master/Utilities/cmcppdap/include/dap/optional.h
3158 views
1
// Copyright 2019 Google LLC
2
//
3
// Licensed under the Apache License, Version 2.0 (the "License");
4
// you may not use this file except in compliance with the License.
5
// You may obtain a copy of the License at
6
//
7
// https://www.apache.org/licenses/LICENSE-2.0
8
//
9
// Unless required by applicable law or agreed to in writing, software
10
// distributed under the License is distributed on an "AS IS" BASIS,
11
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
// See the License for the specific language governing permissions and
13
// limitations under the License.
14
15
#ifndef dap_optional_h
16
#define dap_optional_h
17
18
#include <assert.h>
19
#include <type_traits>
20
#include <utility> // std::move, std::forward
21
22
namespace dap {
23
24
// optional holds an 'optional' contained value.
25
// This is similar to C++17's std::optional.
26
template <typename T>
27
class optional {
28
template <typename U>
29
using IsConvertibleToT =
30
typename std::enable_if<std::is_convertible<U, T>::value>::type;
31
32
public:
33
using value_type = T;
34
35
// constructors
36
inline optional() = default;
37
inline optional(const optional& other);
38
inline optional(optional&& other);
39
template <typename U>
40
inline optional(const optional<U>& other);
41
template <typename U>
42
inline optional(optional<U>&& other);
43
template <typename U = value_type, typename = IsConvertibleToT<U>>
44
inline optional(U&& value);
45
46
// value() returns the contained value.
47
// If the optional does not contain a value, then value() will assert.
48
inline T& value();
49
inline const T& value() const;
50
51
// value() returns the contained value, or defaultValue if the optional does
52
// not contain a value.
53
inline const T& value(const T& defaultValue) const;
54
55
// operator bool() returns true if the optional contains a value.
56
inline explicit operator bool() const noexcept;
57
58
// has_value() returns true if the optional contains a value.
59
inline bool has_value() const;
60
61
// assignment
62
inline optional& operator=(const optional& other);
63
inline optional& operator=(optional&& other) noexcept;
64
template <typename U = T, typename = IsConvertibleToT<U>>
65
inline optional& operator=(U&& value);
66
template <typename U>
67
inline optional& operator=(const optional<U>& other);
68
template <typename U>
69
inline optional& operator=(optional<U>&& other);
70
71
// value access
72
inline const T* operator->() const;
73
inline T* operator->();
74
inline const T& operator*() const;
75
inline T& operator*();
76
77
private:
78
T val{};
79
bool set = false;
80
};
81
82
template <typename T>
83
optional<T>::optional(const optional& other) : val(other.val), set(other.set) {}
84
85
template <typename T>
86
optional<T>::optional(optional&& other)
87
: val(std::move(other.val)), set(other.set) {}
88
89
template <typename T>
90
template <typename U>
91
optional<T>::optional(const optional<U>& other) : set(other.has_value()) {
92
if (set) {
93
val = static_cast<T>(other.value());
94
}
95
}
96
97
template <typename T>
98
template <typename U>
99
optional<T>::optional(optional<U>&& other) : set(other.has_value()) {
100
if (set) {
101
val = static_cast<T>(std::move(other.value()));
102
}
103
}
104
105
template <typename T>
106
template <typename U /*= T*/, typename>
107
optional<T>::optional(U&& value) : val(std::forward<U>(value)), set(true) {}
108
109
template <typename T>
110
T& optional<T>::value() {
111
assert(set);
112
return val;
113
}
114
115
template <typename T>
116
const T& optional<T>::value() const {
117
assert(set);
118
return val;
119
}
120
121
template <typename T>
122
const T& optional<T>::value(const T& defaultValue) const {
123
if (!has_value()) {
124
return defaultValue;
125
}
126
return val;
127
}
128
129
template <typename T>
130
optional<T>::operator bool() const noexcept {
131
return set;
132
}
133
134
template <typename T>
135
bool optional<T>::has_value() const {
136
return set;
137
}
138
139
template <typename T>
140
optional<T>& optional<T>::operator=(const optional& other) {
141
val = other.val;
142
set = other.set;
143
return *this;
144
}
145
146
template <typename T>
147
optional<T>& optional<T>::operator=(optional&& other) noexcept {
148
val = std::move(other.val);
149
set = other.set;
150
return *this;
151
}
152
153
template <typename T>
154
template <typename U /* = T */, typename>
155
optional<T>& optional<T>::operator=(U&& value) {
156
val = std::forward<U>(value);
157
set = true;
158
return *this;
159
}
160
161
template <typename T>
162
template <typename U>
163
optional<T>& optional<T>::operator=(const optional<U>& other) {
164
val = other.val;
165
set = other.set;
166
return *this;
167
}
168
169
template <typename T>
170
template <typename U>
171
optional<T>& optional<T>::operator=(optional<U>&& other) {
172
val = std::move(other.val);
173
set = other.set;
174
return *this;
175
}
176
177
template <typename T>
178
const T* optional<T>::operator->() const {
179
assert(set);
180
return &val;
181
}
182
183
template <typename T>
184
T* optional<T>::operator->() {
185
assert(set);
186
return &val;
187
}
188
189
template <typename T>
190
const T& optional<T>::operator*() const {
191
assert(set);
192
return val;
193
}
194
195
template <typename T>
196
T& optional<T>::operator*() {
197
assert(set);
198
return val;
199
}
200
201
template <class T, class U>
202
inline bool operator==(const optional<T>& lhs, const optional<U>& rhs) {
203
if (!lhs.has_value() && !rhs.has_value()) {
204
return true;
205
}
206
if (!lhs.has_value() || !rhs.has_value()) {
207
return false;
208
}
209
return lhs.value() == rhs.value();
210
}
211
212
template <class T, class U>
213
inline bool operator!=(const optional<T>& lhs, const optional<U>& rhs) {
214
return !(lhs == rhs);
215
}
216
217
template <class T, class U>
218
inline bool operator<(const optional<T>& lhs, const optional<U>& rhs) {
219
if (!rhs.has_value()) {
220
return false;
221
}
222
if (!lhs.has_value()) {
223
return true;
224
}
225
return lhs.value() < rhs.value();
226
}
227
228
template <class T, class U>
229
inline bool operator<=(const optional<T>& lhs, const optional<U>& rhs) {
230
if (!lhs.has_value()) {
231
return true;
232
}
233
if (!rhs.has_value()) {
234
return false;
235
}
236
return lhs.value() <= rhs.value();
237
}
238
239
template <class T, class U>
240
inline bool operator>(const optional<T>& lhs, const optional<U>& rhs) {
241
if (!lhs.has_value()) {
242
return false;
243
}
244
if (!rhs.has_value()) {
245
return true;
246
}
247
return lhs.value() > rhs.value();
248
}
249
250
template <class T, class U>
251
inline bool operator>=(const optional<T>& lhs, const optional<U>& rhs) {
252
if (!rhs.has_value()) {
253
return true;
254
}
255
if (!lhs.has_value()) {
256
return false;
257
}
258
return lhs.value() >= rhs.value();
259
}
260
261
} // namespace dap
262
263
#endif // dap_optional_h
264
265