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