• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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