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