1 // Copyright 2019 The Android Open Source Project
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 // http://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 #pragma once
16
17 #include "aemu/base/TypeTraits.h"
18
19 #if __has_include("host-common/logging.h")
20 #include "host-common/logging.h"
21 #else
22 #define ERR(x) void (0)
23 #endif
24
25 #include <cassert>
26 #include <initializer_list>
27 #include <type_traits>
28 #include <utility>
29
30 #include <cstddef>
31
32 // Optional<T> - a template class to store an optional value of type T.
33 //
34 // Usage examples:
35 //
36 // Initialization and construction:
37 // Optional<Foo> foo; // |foo| doesn't contain a value.
38 // Optional<Foo> foo(Foo(10)); // |foo| contains a copy-constructed value.
39 // Optional<Foo> foo2(foo); // |foo2| contains a copy of |foo|'s value.
40 // Optional<Foo> foo3(std::move(foo2)); // Guess what?
41 //
42 // Assignment:
43 // Foo foo_value(0);
44 // Optional<Foo> foo; // |foo| is empty.
45 // Optional<Foo> foo2; // |foo2| is empty.
46 // foo2 = foo; // |foo2| is still empty.
47 // foo = foo_value; // set value of |foo| to a copy of |foo_value|
48 // foo = std::move(foo_value); // move |foo_value| into |foo|.
49 // foo2 = foo; // now |foo2| has a copy of |foo|'s value.
50 // foo = kNullopt; // unset |foo|, it has no value.
51 //
52 // Checking and accessing value:
53 // if (foo) {
54 // // |foo| has a value.
55 // doStuff(*foo); // |*foo| is the value inside |foo|.
56 // foo->callMethod(); // Same as (*foo).callMethod().
57 // } else {
58 // // |foo| is empty.
59 // }
60 //
61 // foo.value() // Same as *foo
62 // foo.valueOr(<default>) // Return <default> is |foo| has no value.
63 //
64 // In-place construction:
65 //
66 // Optional<Foo> foo; // |foo| is empty.
67 // foo.emplace(20); // |foo| now contains a value constructed as Foo(20)
68 //
69 // Optional<Foo> foo(kInplace, 20); // |foo| is initialized with a value
70 // // that is constructed in-place as
71 // // Foo(20).
72 //
73 // return makeOptional<Foo>(20); // Takes Foo constructor arguments
74 // // directly.
75 //
76 // Returning values:
77 //
78 // Optional<Foo> myFunc(...) {
79 // if (someCondition) {
80 // return Foo(10); // call Optional<Foo>(Foo&) constructor.
81 // } else {
82 // return {}; // call Optional<Foo>() constructor, which
83 // // builds an empty value.
84 // }
85 // }
86 //
87 // Memory layout:
88 // Optional<Foo> is equivalent to:
89 //
90 // struct {
91 // bool flag;
92 // Foo value;
93 // };
94 //
95 // in terms of memory layout. This means it *doubles* the size of integral
96 // types. Also:
97 //
98 // - Optional<Foo> can be constructed from anything that constructs a Foo.
99 //
100 // - Same with Optional<Foo>(kInplace, Args...) where Args... matches any
101 // arguments that can be passed to a Foo constructor.
102 //
103 // - Comparison operators are provided. Beware: an empty Optional<Foo>
104 // is always smaller than any Foo value.
105
106 namespace android {
107 namespace base {
108
109 namespace details {
110
111 // Base classes to reduce the number of instantiations of the Optional's
112 // internal members.
113 class OptionalFlagBase {
114 public:
setConstructed(bool constructed)115 void setConstructed(bool constructed) { mConstructed = constructed; }
constructed()116 constexpr bool constructed() const { return mConstructed; }
117 constexpr operator bool() const { return constructed(); }
hasValue()118 bool hasValue() const { return constructed(); }
119
120 constexpr OptionalFlagBase(bool constructed = false)
mConstructed(constructed)121 : mConstructed(constructed) {}
122
123 private:
124 bool mConstructed = false;
125 };
126
127 template <size_t Size, size_t Align>
128 class OptionalStorageBase {
129 protected:
130 using StoreT = typename std::aligned_storage<Size, Align>::type;
131 StoreT mStorage = {};
132 };
133
134 } // namespace details
135
136 // A tag type for empty optional construction
137 struct NulloptT {
NulloptTNulloptT138 constexpr explicit NulloptT(int) {}
139 };
140
141 // A tag type for inplace value construction
142 struct InplaceT {
InplaceTInplaceT143 constexpr explicit InplaceT(int) {}
144 };
145
146 // Tag values for null optional and inplace construction
147 constexpr NulloptT kNullopt{1};
148 constexpr InplaceT kInplace{1};
149
150 // Forward declaration for an early use
151 template <class T>
152 class Optional;
153
154 // A type trait for checking if a type is an optional instantiation
155 // Note: if you want to refer to the template name inside the template,
156 // you need to declare this alias outside of it - because the
157 // class name inside of the template stands for an instantiated template
158 // E.g, for template <T> class Foo if you say 'Foo' inside the class, it
159 // actually means Foo<T>;
160 template <class U>
161 using is_any_optional =
162 is_template_instantiation_of<typename std::decay<U>::type, Optional>;
163
164 template <class T>
165 class Optional
166 : private details::OptionalFlagBase,
167 private details::OptionalStorageBase<sizeof(T),
168 std::alignment_of<T>::value> {
169 // make sure all optionals are buddies - this is needed to implement
170 // conversion from optionals of other types
171 template <class U>
172 friend class Optional;
173
174 template <class U>
175 using self = Optional<U>;
176
177 using base_flag = details::OptionalFlagBase;
178 using base_storage =
179 details::OptionalStorageBase<sizeof(T),
180 std::alignment_of<T>::value>;
181
182 public:
183 // std::optional will have this, so let's provide it
184 using value_type = T;
185
186 // make sure we forbid some Optional instantiations where things may get
187 // really messy
188 static_assert(!std::is_same<typename std::decay<T>::type, NulloptT>::value,
189 "Optional of NulloptT is not allowed");
190 static_assert(!std::is_same<typename std::decay<T>::type, InplaceT>::value,
191 "Optional of InplaceT is not allowed");
192 static_assert(!std::is_reference<T>::value,
193 "Optional references are not allowed: use a pointer instead");
194
195 // constructors
Optional()196 constexpr Optional() {}
Optional(NulloptT)197 constexpr Optional(NulloptT) {}
198
Optional(const Optional & other)199 Optional(const Optional& other) : base_flag(other.constructed()) {
200 if (this->constructed()) {
201 new (&get()) T(other.get());
202 }
203 }
Optional(Optional && other)204 Optional(Optional&& other) : base_flag(other.constructed()) {
205 if (this->constructed()) {
206 new (&get()) T(std::move(other.get()));
207 }
208 }
209
210 // Conversion constructor from optional of similar type
211 template <class U,
212 class = enable_if_c<!is_any_optional<U>::value &&
213 std::is_constructible<T, U>::value>>
Optional(const Optional<U> & other)214 Optional(const Optional<U>& other) : base_flag(other.constructed()) {
215 if (this->constructed()) {
216 new (&get()) T(other.get());
217 }
218 }
219
220 // Move-conversion constructor
221 template <class U,
222 class = enable_if_c<!is_any_optional<U>::value &&
223 std::is_constructible<T, U>::value>>
Optional(Optional<U> && other)224 Optional(Optional<U>&& other) : base_flag(other.constructed()) {
225 if (this->constructed()) {
226 new (&get()) T(std::move(other.get()));
227 }
228 }
229
230 // Construction from a raw value
Optional(const T & value)231 Optional(const T& value) : base_flag(true) { new (&get()) T(value); }
232 // Move construction from a raw value
Optional(T && value)233 Optional(T&& value) : base_flag(true) { new (&get()) T(std::move(value)); }
234
235 // Inplace construction from a list of |T|'s ctor arguments
236 template <class... Args>
Optional(InplaceT,Args &&...args)237 Optional(InplaceT, Args&&... args) : base_flag(true) {
238 new (&get()) T(std::forward<Args>(args)...);
239 }
240
241 // Inplace construction from an initializer list passed into |T|'s ctor
242 template <class U,
243 class = enable_if<
244 std::is_constructible<T, std::initializer_list<U>>>>
Optional(InplaceT,std::initializer_list<U> il)245 Optional(InplaceT, std::initializer_list<U> il) : base_flag(true) {
246 new (&get()) T(il);
247 }
248
249 // direct assignment
250 Optional& operator=(const Optional& other) {
251 if (&other == this) {
252 return *this;
253 }
254
255 if (this->constructed()) {
256 if (other.constructed()) {
257 get() = other.get();
258 } else {
259 destruct();
260 this->setConstructed(false);
261 }
262 } else {
263 if (other.constructed()) {
264 new (&get()) T(other.get());
265 this->setConstructed(true);
266 } else {
267 ; // we're good
268 }
269 }
270 return *this;
271 }
272
273 // move assignment
274 Optional& operator=(Optional&& other) {
275 if (this->constructed()) {
276 if (other.constructed()) {
277 get() = std::move(other.get());
278 } else {
279 destruct();
280 this->setConstructed(false);
281 }
282 } else {
283 if (other.constructed()) {
284 new (&get()) T(std::move(other.get()));
285 this->setConstructed(true);
286 } else {
287 ; // we're good
288 }
289 }
290 return *this;
291 }
292
293 // conversion assignment
294 template <class U,
295 class = enable_if_convertible<typename std::decay<U>::type, T>>
296 Optional& operator=(const Optional<U>& other) {
297 if (this->constructed()) {
298 if (other.constructed()) {
299 get() = other.get();
300 } else {
301 destruct();
302 this->setConstructed(false);
303 }
304 } else {
305 if (other.constructed()) {
306 new (&get()) T(other.get());
307 this->setConstructed(true);
308 } else {
309 ; // we're good
310 }
311 }
312 return *this;
313 }
314
315 // conversion move assignment
316 template <class U,
317 class = enable_if_convertible<typename std::decay<U>::type, T>>
318 Optional& operator=(Optional<U>&& other) {
319 if (this->constructed()) {
320 if (other.constructed()) {
321 get() = std::move(other.get());
322 } else {
323 destruct();
324 this->setConstructed(false);
325 }
326 } else {
327 if (other.constructed()) {
328 new (&get()) T(std::move(other.get()));
329 this->setConstructed(true);
330 } else {
331 ; // we're good
332 }
333 }
334 return *this;
335 }
336
337 // the most complicated one: forwarding constructor for anything convertible
338 // to |T|, excluding the stuff implemented above explicitly
339 template <class U,
340 class = enable_if_c<
341 !is_any_optional<typename std::decay<U>::type>::value &&
342 std::is_convertible<typename std::decay<U>::type,
343 T>::value>>
344 Optional& operator=(U&& other) {
345 if (this->constructed()) {
346 get() = std::forward<U>(other);
347 } else {
348 new (&get()) T(std::forward<U>(other));
349 this->setConstructed(true);
350 }
351 return *this;
352 }
353
354 // Adopt value checkers from the parent
355 using base_flag::operator bool;
356 using base_flag::hasValue;
357
value()358 T& value() {
359 if (!constructed()) {
360 ERR("Optional not constructed");
361 abort();
362 }
363 return get();
364 }
value()365 constexpr const T& value() const {
366 if (!constructed()) {
367 ERR("Optional not constructed");
368 abort();
369 }
370 return get();
371 }
372
ptr()373 T* ptr() {
374 return this->constructed() ? &get() : nullptr;
375 }
ptr()376 constexpr const T* ptr() const {
377 return this->constructed() ? &get() : nullptr;
378 }
379
380 // Value getter with fallback
381 template <class U = T,
382 class = enable_if_convertible<typename std::decay<U>::type, T>>
valueOr(U && defaultValue)383 constexpr T valueOr(U&& defaultValue) const {
384 return this->constructed() ? get() : std::move(defaultValue);
385 }
386
387 // Pointer-like operators
388 T& operator*() {
389 if (!constructed()) {
390 ERR("Optional not constructed");
391 abort();
392 }
393 return get();
394 }
395 constexpr const T& operator*() const {
396 if (!constructed()) {
397 ERR("Optional not constructed");
398 abort();
399 }
400 return get();
401 }
402
403 T* operator->() {
404 if (!constructed()) {
405 ERR("Optional not constructed");
406 abort();
407 }
408 return &get();
409 }
410 constexpr const T* operator->() const {
411 if (!constructed()) {
412 ERR("Optional not constructed");
413 abort();
414 }
415 return &get();
416 }
417
~Optional()418 ~Optional() {
419 if (this->constructed()) {
420 destruct();
421 }
422 }
423
clear()424 void clear() {
425 if (this->constructed()) {
426 destruct();
427 this->setConstructed(false);
428 }
429 }
430
431 template <class U,
432 class = enable_if_convertible<typename std::decay<U>::type, T>>
reset(U && u)433 void reset(U&& u) {
434 *this = std::forward<U>(u);
435 }
436
437 // In-place construction with possible destruction of the old value
438 template <class... Args>
emplace(Args &&...args)439 void emplace(Args&&... args) {
440 if (this->constructed()) {
441 destruct();
442 }
443 new (&get()) T(std::forward<Args>(args)...);
444 this->setConstructed(true);
445 }
446
447 // In-place construction with possible destruction of the old value
448 // initializer-list version
449 template <class U,
450 class = enable_if<
451 std::is_constructible<T, std::initializer_list<U>>>>
emplace(std::initializer_list<U> il)452 void emplace(std::initializer_list<U> il) {
453 if (this->constructed()) {
454 destruct();
455 }
456 new (&get()) T(il);
457 this->setConstructed(true);
458 }
459
460 private:
461 // A helper function to convert the internal raw storage to T&
get()462 constexpr const T& get() const {
463 return *reinterpret_cast<const T*>(
464 reinterpret_cast<const char*>(&this->mStorage));
465 }
466
467 // Same thing, mutable
get()468 T& get() {
469 return const_cast<T&>(const_cast<const Optional*>(this)->get());
470 }
471
472 // Shortcut for a destructor call for the stored object
destruct()473 void destruct() { get().T::~T(); }
474 };
475
476 template <class T>
makeOptional(T && t)477 Optional<typename std::decay<T>::type> makeOptional(T&& t) {
478 return Optional<typename std::decay<T>::type>(std::forward<T>(t));
479 }
480
481 template <class T, class... Args>
makeOptional(Args &&...args)482 Optional<typename std::decay<T>::type> makeOptional(Args&&... args) {
483 return Optional<typename std::decay<T>::type>(kInplace,
484 std::forward<Args>(args)...);
485 }
486
487 template <class T>
488 bool operator==(const Optional<T>& l, const Optional<T>& r) {
489 return l.hasValue() ? r.hasValue() && *l == *r : !r.hasValue();
490 }
491 template <class T>
492 bool operator==(const Optional<T>& l, NulloptT) {
493 return !l;
494 }
495 template <class T>
496 bool operator==(NulloptT, const Optional<T>& r) {
497 return !r;
498 }
499 template <class T>
500 bool operator==(const Optional<T>& l, const T& r) {
501 return bool(l) && *l == r;
502 }
503 template <class T>
504 bool operator==(const T& l, const Optional<T>& r) {
505 return bool(r) && l == *r;
506 }
507
508 template <class T>
509 bool operator!=(const Optional<T>& l, const Optional<T>& r) {
510 return !(l == r);
511 }
512 template <class T>
513 bool operator!=(const Optional<T>& l, NulloptT) {
514 return bool(l);
515 }
516 template <class T>
517 bool operator!=(NulloptT, const Optional<T>& r) {
518 return bool(r);
519 }
520 template <class T>
521 bool operator!=(const Optional<T>& l, const T& r) {
522 return !l || !(*l == r);
523 }
524 template <class T>
525 bool operator!=(const T& l, const Optional<T>& r) {
526 return !r || !(l == *r);
527 }
528
529 template <class T>
530 bool operator<(const Optional<T>& l, const Optional<T>& r) {
531 return !r ? false : (!l ? true : *l < *r);
532 }
533 template <class T>
534 bool operator<(const Optional<T>&, NulloptT) {
535 return false;
536 }
537 template <class T>
538 bool operator<(NulloptT, const Optional<T>& r) {
539 return bool(r);
540 }
541 template <class T>
542 bool operator<(const Optional<T>& l, const T& r) {
543 return !l || *l < r;
544 }
545 template <class T>
546 bool operator<(const T& l, const Optional<T>& r) {
547 return bool(r) && l < *r;
548 }
549
550 } // namespace base
551 } // namespace android
552