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