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