Woman, Life, Freedom


Adaptive AUTOSAR
ARA public interface header documentation
optional.h
1#ifndef OPTIONAL_H
2#define OPTIONAL_H
3
4#include <type_traits>
5#include <utility>
6#include <stdexcept>
7
8namespace ara
9{
10 namespace core
11 {
14 template <typename T>
16 {
17 private:
18 T *mValuePtr;
19
20 public:
21 constexpr Optional() noexcept : mValuePtr{nullptr}
22 {
23 }
24
25 Optional(const T &value)
26 {
27 mValuePtr = new T{value};
28 }
29
30 Optional(T &&value)
31 {
32 mValuePtr = new T{std::move(value)};
33 }
34
35 Optional(const Optional &other)
36 {
37 mValuePtr = other.HasValue() ? new T{*other.mValuePtr} : nullptr;
38 }
39
40 Optional(Optional &&other) noexcept(
41 std::is_nothrow_move_assignable<T>::value)
42 {
43 if (other.HasValue())
44 {
45 mValuePtr = other.mValuePtr;
46 other.mValuePtr = nullptr;
47 }
48 else
49 {
50 mValuePtr = nullptr;
51 }
52 }
53
54 ~Optional()
55 {
56 Reset();
57 }
58
59 constexpr Optional &operator=(const Optional &other)
60 {
61 Reset();
62
63 if (other.HasValue())
64 {
65 mValuePtr = new T{*other.mValuePtr};
66 }
67
68 return *this;
69 }
70
71 constexpr Optional &operator=(Optional &&other) noexcept(
72 std::is_nothrow_move_assignable<T>::value)
73 {
74 Reset();
75
76 if (other.HasValue())
77 {
78 mValuePtr = other.mValuePtr;
79 other.mValuePtr = nullptr;
80 }
81
82 return *this;
83 }
84
85 template <typename U = T>
86 constexpr Optional &operator=(const U &value)
87 {
88 Reset();
89 mValuePtr = new T{static_cast<const T &>(value)};
90
91 return *this;
92 }
93
94 template <typename U = T>
95 constexpr Optional &operator=(U &&value)
96 {
97 Reset();
98 mValuePtr = new T{static_cast<T &&>(value)};
99
100 return *this;
101 }
102
105 template <typename... Args>
106 void Emplace(Args &&...args)
107 {
108 Reset();
109 mValuePtr = new T{args...};
110 }
111
114 void Swap(Optional &other) noexcept(
115 std::is_nothrow_move_assignable<T>::value)
116 {
117 if (HasValue() && other.HasValue())
118 {
119 std::swap(mValuePtr, other.mValuePtr);
120 }
121 else if (HasValue() && !other.HasValue())
122 {
123 other.mValuePtr = mValuePtr;
124 mValuePtr = nullptr;
125 }
126 else if (!HasValue() && other.HasValue())
127 {
128 mValuePtr = other.mValuePtr;
129 other.mValuePtr = nullptr;
130 }
131 }
132
134 void Reset() noexcept
135 {
136 if (HasValue())
137 {
138 delete mValuePtr;
139 mValuePtr = nullptr;
140 }
141 }
142
145 constexpr bool HasValue() const noexcept
146 {
147 return mValuePtr != nullptr;
148 }
149
151 constexpr explicit operator bool() const noexcept
152 {
153 return HasValue();
154 }
155
158 const T &operator*() const &
159 {
160 if (HasValue())
161 {
162 return *mValuePtr;
163 }
164 else
165 {
166 throw std::runtime_error("Optional contains no value.");
167 }
168 }
169
172 T &&operator*() &&
173 {
174 if (HasValue())
175 {
176 return std::move(*mValuePtr);
177 }
178 else
179 {
180 throw std::runtime_error("Optional contains no value.");
181 }
182 }
183
186 const T *operator->() const
187 {
188 if (HasValue())
189 {
190 mValuePtr;
191 }
192 else
193 {
194 throw std::runtime_error("Optional contains no value.");
195 }
196 }
197
201 const T &Value() const &
202 {
203 if (HasValue())
204 {
205 return *mValuePtr;
206 }
207 else
208 {
209 throw std::runtime_error("Optional contains no value.");
210 }
211 }
212
216 T &&Value() &&
217 {
218 if (HasValue())
219 {
220 T *_result{mValuePtr};
221 mValuePtr = nullptr;
222
223 return std::move(*_result);
224 }
225 else
226 {
227 throw std::runtime_error("Optional contains no value.");
228 }
229 }
230
235 template <typename U>
236 T ValueOr(U &&defaultValue) const &
237 {
238 if (HasValue())
239 {
240 return *mValuePtr;
241 }
242 else
243 {
244 return static_cast<T>(defaultValue);
245 }
246 }
247
252 template <typename U>
253 T ValueOr(U &&defaultValue) &&
254 {
255 if (HasValue())
256 {
257 return std::move(*mValuePtr);
258 }
259 else
260 {
261 return static_cast<T>(defaultValue);
262 }
263 }
264 };
265
267 template <typename T>
268 inline bool operator==(const Optional<T> &lhs, const Optional<T> &rhs) noexcept
269 {
270 bool _result;
271
272 if (lhs.HasValue() && rhs.HasValue())
273 {
274 _result = lhs.Value() == rhs.Value();
275 }
276 else if (!lhs.HasValue() && !rhs.HasValue())
277 {
278 _result = true;
279 }
280 else
281 {
282 _result = false;
283 }
284
285 return _result;
286 }
287
289 template <typename T>
290 inline bool operator!=(const Optional<T> &lhs, const Optional<T> &rhs) noexcept
291 {
292 bool _result;
293
294 if (lhs.HasValue() && rhs.HasValue())
295 {
296 _result = lhs.Value() != rhs.Value();
297 }
298 else if (!lhs.HasValue() && !rhs.HasValue())
299 {
300 _result = false;
301 }
302 else
303 {
304 _result = true;
305 }
306
307 return _result;
308 }
309 }
310}
311
312#endif
A wrapper around a possible value.
Definition: optional.h:16
T && Value() &&
Get instance possible value.
Definition: optional.h:216
void Reset() noexcept
Reset the instance value.
Definition: optional.h:134
const T & operator*() const &
Definition: optional.h:158
constexpr bool HasValue() const noexcept
Indicate whether the instance has a value or not.
Definition: optional.h:145
T && operator*() &&
Definition: optional.h:172
const T * operator->() const
Definition: optional.h:186
T ValueOr(U &&defaultValue) const &
Get the instance value or the default value.
Definition: optional.h:236
void Emplace(Args &&...args)
Construct a new value from the give argument(s) and assign it to the instance value.
Definition: optional.h:106
const T & Value() const &
Get instance possible value.
Definition: optional.h:201
void Swap(Optional &other) noexcept(std::is_nothrow_move_assignable< T >::value)
Swap the current instance with another one.
Definition: optional.h:114
T ValueOr(U &&defaultValue) &&
Get the instance value or the default value.
Definition: optional.h:253