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