• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2018 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #ifndef INCLUDE_PERFETTO_EXT_BASE_OPTIONAL_H_
18 #define INCLUDE_PERFETTO_EXT_BASE_OPTIONAL_H_
19 
20 #include <functional>
21 #include <type_traits>
22 #include <utility>
23 
24 #include "perfetto/base/logging.h"
25 
26 namespace perfetto {
27 namespace base {
28 
29 // Specification:
30 // http://en.cppreference.com/w/cpp/utility/optional/in_place_t
31 struct in_place_t {};
32 
33 // Specification:
34 // http://en.cppreference.com/w/cpp/utility/optional/nullopt_t
35 struct nullopt_t {
nullopt_tnullopt_t36   constexpr explicit nullopt_t(int) {}
37 };
38 
39 // Specification:
40 // http://en.cppreference.com/w/cpp/utility/optional/in_place
41 constexpr in_place_t in_place = {};
42 
43 // Specification:
44 // http://en.cppreference.com/w/cpp/utility/optional/nullopt
45 constexpr nullopt_t nullopt(0);
46 
47 // Forward declaration, which is referred by following helpers.
48 template <typename T>
49 class Optional;
50 
51 namespace internal {
52 
53 template <typename T, bool = std::is_trivially_destructible<T>::value>
54 struct OptionalStorageBase {
55   // Initializing |empty_| here instead of using default member initializing
56   // to avoid errors in g++ 4.8.
OptionalStorageBaseOptionalStorageBase57   constexpr OptionalStorageBase() : empty_('\0') {}
58 
59   template <class... Args>
OptionalStorageBaseOptionalStorageBase60   constexpr explicit OptionalStorageBase(in_place_t, Args&&... args)
61       : is_populated_(true), value_(std::forward<Args>(args)...) {}
62 
63   // When T is not trivially destructible we must call its
64   // destructor before deallocating its memory.
65   // Note that this hides the (implicitly declared) move constructor, which
66   // would be used for constexpr move constructor in OptionalStorage<T>.
67   // It is needed iff T is trivially move constructible. However, the current
68   // is_trivially_{copy,move}_constructible implementation requires
69   // is_trivially_destructible (which looks a bug, cf:
70   // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=51452 and
71   // http://cplusplus.github.io/LWG/lwg-active.html#2116), so it is not
72   // necessary for this case at the moment. Please see also the destructor
73   // comment in "is_trivially_destructible = true" specialization below.
~OptionalStorageBaseOptionalStorageBase74   ~OptionalStorageBase() {
75     if (is_populated_)
76       value_.~T();
77   }
78 
79   template <class... Args>
InitOptionalStorageBase80   void Init(Args&&... args) {
81     PERFETTO_DCHECK(!is_populated_);
82     ::new (&value_) T(std::forward<Args>(args)...);
83     is_populated_ = true;
84   }
85 
86   bool is_populated_ = false;
87   union {
88     // |empty_| exists so that the union will always be initialized, even when
89     // it doesn't contain a value. Union members must be initialized for the
90     // constructor to be 'constexpr'.
91     char empty_;
92     T value_;
93   };
94 };
95 
96 template <typename T>
97 struct OptionalStorageBase<T, true /* trivially destructible */> {
98   // Initializing |empty_| here instead of using default member initializing
99   // to avoid errors in g++ 4.8.
100   constexpr OptionalStorageBase() : empty_('\0') {}
101 
102   template <class... Args>
103   constexpr explicit OptionalStorageBase(in_place_t, Args&&... args)
104       : is_populated_(true), value_(std::forward<Args>(args)...) {}
105 
106   // When T is trivially destructible (i.e. its destructor does nothing) there
107   // is no need to call it. Implicitly defined destructor is trivial, because
108   // both members (bool and union containing only variants which are trivially
109   // destructible) are trivially destructible.
110   // Explicitly-defaulted destructor is also trivial, but do not use it here,
111   // because it hides the implicit move constructor. It is needed to implement
112   // constexpr move constructor in OptionalStorage iff T is trivially move
113   // constructible. Note that, if T is trivially move constructible, the move
114   // constructor of OptionalStorageBase<T> is also implicitly defined and it is
115   // trivially move constructor. If T is not trivially move constructible,
116   // "not declaring move constructor without destructor declaration" here means
117   // "delete move constructor", which works because any move constructor of
118   // OptionalStorage will not refer to it in that case.
119 
120   template <class... Args>
121   void Init(Args&&... args) {
122     PERFETTO_DCHECK(!is_populated_);
123     ::new (&value_) T(std::forward<Args>(args)...);
124     is_populated_ = true;
125   }
126 
127   bool is_populated_ = false;
128   union {
129     // |empty_| exists so that the union will always be initialized, even when
130     // it doesn't contain a value. Union members must be initialized for the
131     // constructor to be 'constexpr'.
132     char empty_;
133     T value_;
134   };
135 };
136 
137 // Implement conditional constexpr copy and move constructors. These are
138 // constexpr if is_trivially_{copy,move}_constructible<T>::value is true
139 // respectively. If each is true, the corresponding constructor is defined as
140 // "= default;", which generates a constexpr constructor (In this case,
141 // the condition of constexpr-ness is satisfied because the base class also has
142 // compiler generated constexpr {copy,move} constructors). Note that
143 // placement-new is prohibited in constexpr.
144 template <typename T, bool = std::is_trivially_copy_constructible<T>::value>
145 struct OptionalStorage : OptionalStorageBase<T> {
146   // This is no trivially {copy,move} constructible case. Other cases are
147   // defined below as specializations.
148 
149   // Accessing the members of template base class requires explicit
150   // declaration.
151   using OptionalStorageBase<T>::is_populated_;
152   using OptionalStorageBase<T>::value_;
153   using OptionalStorageBase<T>::Init;
154 
155   // Inherit constructors (specifically, the in_place constructor).
156   using OptionalStorageBase<T>::OptionalStorageBase;
157 
158   // User defined constructor deletes the default constructor.
159   // Define it explicitly.
160   OptionalStorage() = default;
161 
162   OptionalStorage(const OptionalStorage& other) : OptionalStorageBase<T>() {
163     if (other.is_populated_)
164       Init(other.value_);
165   }
166 
167   OptionalStorage(OptionalStorage&& other) noexcept(
168       std::is_nothrow_move_constructible<T>::value) {
169     if (other.is_populated_)
170       Init(std::move(other.value_));
171   }
172 };
173 
174 template <typename T>
175 struct OptionalStorage<T, true /* trivially copy constructible */>
176     : OptionalStorageBase<T> {
177   using OptionalStorageBase<T>::is_populated_;
178   using OptionalStorageBase<T>::value_;
179   using OptionalStorageBase<T>::Init;
180   using OptionalStorageBase<T>::OptionalStorageBase;
181 
182   OptionalStorage() = default;
183   OptionalStorage(const OptionalStorage& other) = default;
184 
185   OptionalStorage(OptionalStorage&& other) noexcept(
186       std::is_nothrow_move_constructible<T>::value) {
187     if (other.is_populated_)
188       Init(std::move(other.value_));
189   }
190 };
191 
192 // Base class to support conditionally usable copy-/move- constructors
193 // and assign operators.
194 template <typename T>
195 class OptionalBase {
196   // This class provides implementation rather than public API, so everything
197   // should be hidden. Often we use composition, but we cannot in this case
198   // because of C++ language restriction.
199  protected:
200   constexpr OptionalBase() = default;
201   constexpr OptionalBase(const OptionalBase& other) = default;
202   constexpr OptionalBase(OptionalBase&& other) = default;
203 
204   template <class... Args>
205   constexpr explicit OptionalBase(in_place_t, Args&&... args)
206       : storage_(in_place, std::forward<Args>(args)...) {}
207 
208   // Implementation of converting constructors.
209   template <typename U>
210   explicit OptionalBase(const OptionalBase<U>& other) {
211     if (other.storage_.is_populated_)
212       storage_.Init(other.storage_.value_);
213   }
214 
215   template <typename U>
216   explicit OptionalBase(OptionalBase<U>&& other) {
217     if (other.storage_.is_populated_)
218       storage_.Init(std::move(other.storage_.value_));
219   }
220 
221   ~OptionalBase() = default;
222 
223   OptionalBase& operator=(const OptionalBase& other) {
224     CopyAssign(other);
225     return *this;
226   }
227 
228   OptionalBase& operator=(OptionalBase&& other) noexcept(
229       std::is_nothrow_move_assignable<T>::value&&
230           std::is_nothrow_move_constructible<T>::value) {
231     MoveAssign(std::move(other));
232     return *this;
233   }
234 
235   template <typename U>
236   void CopyAssign(const OptionalBase<U>& other) {
237     if (other.storage_.is_populated_)
238       InitOrAssign(other.storage_.value_);
239     else
240       FreeIfNeeded();
241   }
242 
243   template <typename U>
244   void MoveAssign(OptionalBase<U>&& other) {
245     if (other.storage_.is_populated_)
246       InitOrAssign(std::move(other.storage_.value_));
247     else
248       FreeIfNeeded();
249   }
250 
251   template <typename U>
252   void InitOrAssign(U&& value) {
253     if (storage_.is_populated_)
254       storage_.value_ = std::forward<U>(value);
255     else
256       storage_.Init(std::forward<U>(value));
257   }
258 
259   void FreeIfNeeded() {
260     if (!storage_.is_populated_)
261       return;
262     storage_.value_.~T();
263     storage_.is_populated_ = false;
264   }
265 
266   // For implementing conversion, allow access to other typed OptionalBase
267   // class.
268   template <typename U>
269   friend class OptionalBase;
270 
271   OptionalStorage<T> storage_;
272 };
273 
274 // The following {Copy,Move}{Constructible,Assignable} structs are helpers to
275 // implement constructor/assign-operator overloading. Specifically, if T is
276 // is not movable but copyable, Optional<T>'s move constructor should not
277 // participate in overload resolution. This inheritance trick implements that.
278 template <bool is_copy_constructible>
279 struct CopyConstructible {};
280 
281 template <>
282 struct CopyConstructible<false> {
283   constexpr CopyConstructible() = default;
284   constexpr CopyConstructible(const CopyConstructible&) = delete;
285   constexpr CopyConstructible(CopyConstructible&&) = default;
286   CopyConstructible& operator=(const CopyConstructible&) = default;
287   CopyConstructible& operator=(CopyConstructible&&) = default;
288 };
289 
290 template <bool is_move_constructible>
291 struct MoveConstructible {};
292 
293 template <>
294 struct MoveConstructible<false> {
295   constexpr MoveConstructible() = default;
296   constexpr MoveConstructible(const MoveConstructible&) = default;
297   constexpr MoveConstructible(MoveConstructible&&) = delete;
298   MoveConstructible& operator=(const MoveConstructible&) = default;
299   MoveConstructible& operator=(MoveConstructible&&) = default;
300 };
301 
302 template <bool is_copy_assignable>
303 struct CopyAssignable {};
304 
305 template <>
306 struct CopyAssignable<false> {
307   constexpr CopyAssignable() = default;
308   constexpr CopyAssignable(const CopyAssignable&) = default;
309   constexpr CopyAssignable(CopyAssignable&&) = default;
310   CopyAssignable& operator=(const CopyAssignable&) = delete;
311   CopyAssignable& operator=(CopyAssignable&&) = default;
312 };
313 
314 template <bool is_move_assignable>
315 struct MoveAssignable {};
316 
317 template <>
318 struct MoveAssignable<false> {
319   constexpr MoveAssignable() = default;
320   constexpr MoveAssignable(const MoveAssignable&) = default;
321   constexpr MoveAssignable(MoveAssignable&&) = default;
322   MoveAssignable& operator=(const MoveAssignable&) = default;
323   MoveAssignable& operator=(MoveAssignable&&) = delete;
324 };
325 
326 // Helper to conditionally enable converting constructors and assign operators.
327 template <typename T, typename U>
328 struct IsConvertibleFromOptional
329     : std::integral_constant<
330           bool,
331           std::is_constructible<T, Optional<U>&>::value ||
332               std::is_constructible<T, const Optional<U>&>::value ||
333               std::is_constructible<T, Optional<U>&&>::value ||
334               std::is_constructible<T, const Optional<U>&&>::value ||
335               std::is_convertible<Optional<U>&, T>::value ||
336               std::is_convertible<const Optional<U>&, T>::value ||
337               std::is_convertible<Optional<U>&&, T>::value ||
338               std::is_convertible<const Optional<U>&&, T>::value> {};
339 
340 template <typename T, typename U>
341 struct IsAssignableFromOptional
342     : std::integral_constant<
343           bool,
344           IsConvertibleFromOptional<T, U>::value ||
345               std::is_assignable<T&, Optional<U>&>::value ||
346               std::is_assignable<T&, const Optional<U>&>::value ||
347               std::is_assignable<T&, Optional<U>&&>::value ||
348               std::is_assignable<T&, const Optional<U>&&>::value> {};
349 
350 // Forward compatibility for C++17.
351 // Introduce one more deeper nested namespace to avoid leaking using std::swap.
352 namespace swappable_impl {
353 using std::swap;
354 
355 struct IsSwappableImpl {
356   // Tests if swap can be called. Check<T&>(0) returns true_type iff swap is
357   // available for T. Otherwise, Check's overload resolution falls back to
358   // Check(...) declared below thanks to SFINAE, so returns false_type.
359   template <typename T>
360   static auto Check(int)
361       -> decltype(swap(std::declval<T>(), std::declval<T>()), std::true_type());
362 
363   template <typename T>
364   static std::false_type Check(...);
365 };
366 }  // namespace swappable_impl
367 
368 template <typename T>
369 struct IsSwappable : decltype(swappable_impl::IsSwappableImpl::Check<T&>(0)) {};
370 
371 // Forward compatibility for C++20.
372 template <typename T>
373 using RemoveCvRefT =
374     typename std::remove_cv<typename std::remove_reference<T>::type>::type;
375 
376 }  // namespace internal
377 
378 // On Windows, by default, empty-base class optimization does not work,
379 // which means even if the base class is empty struct, it still consumes one
380 // byte for its body. __declspec(empty_bases) enables the optimization.
381 // cf)
382 // https://blogs.msdn.microsoft.com/vcblog/2016/03/30/optimizing-the-layout-of-empty-base-classes-in-vs2015-update-2-3/
383 #if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN) && \
384     !PERFETTO_BUILDFLAG(PERFETTO_COMPILER_GCC)
385 #define OPTIONAL_DECLSPEC_EMPTY_BASES __declspec(empty_bases)
386 #else
387 #define OPTIONAL_DECLSPEC_EMPTY_BASES
388 #endif
389 
390 // base::Optional is a Chromium version of the C++17 optional class:
391 // std::optional documentation:
392 // http://en.cppreference.com/w/cpp/utility/optional
393 // Chromium documentation:
394 // https://chromium.googlesource.com/chromium/src/+/master/docs/optional.md
395 //
396 // These are the differences between the specification and the implementation:
397 // - Constructors do not use 'constexpr' as it is a C++14 extension.
398 // - 'constexpr' might be missing in some places for reasons specified locally.
399 // - No exceptions are thrown, because they are banned from Chromium.
400 //   Marked noexcept for only move constructor and move assign operators.
401 // - All the non-members are in the 'base' namespace instead of 'std'.
402 //
403 // Note that T cannot have a constructor T(Optional<T>) etc. Optional<T>
404 // PERFETTO_CHECKs T's constructor (specifically via IsConvertibleFromOptional),
405 // and in the PERFETTO_CHECK whether T can be constructible from Optional<T>,
406 // which is recursive so it does not work. As of Feb 2018, std::optional C++17
407 // implementation in both clang and gcc has same limitation. MSVC SFINAE looks
408 // to have different behavior, but anyway it reports an error, too.
409 //
410 // This file is a modified version of optional.h from Chromium at revision
411 // 5e71bd454e60511c1293c0c686544aaa76094424. The changes remove C++14/C++17
412 // specific code and replace with C++11 counterparts.
413 template <typename T>
414 class OPTIONAL_DECLSPEC_EMPTY_BASES Optional
415     : public internal::OptionalBase<T>,
416       public internal::CopyConstructible<std::is_copy_constructible<T>::value>,
417       public internal::MoveConstructible<std::is_move_constructible<T>::value>,
418       public internal::CopyAssignable<std::is_copy_constructible<T>::value &&
419                                       std::is_copy_assignable<T>::value>,
420       public internal::MoveAssignable<std::is_move_constructible<T>::value &&
421                                       std::is_move_assignable<T>::value> {
422  public:
423 #undef OPTIONAL_DECLSPEC_EMPTY_BASES
424   using value_type = T;
425 
426   // Defer default/copy/move constructor implementation to OptionalBase.
427   constexpr Optional() = default;
428   constexpr Optional(const Optional& other) = default;
429   constexpr Optional(Optional&& other) noexcept(
430       std::is_nothrow_move_constructible<T>::value) = default;
431 
432   constexpr Optional(nullopt_t) {}  // NOLINT(runtime/explicit)
433 
434   // Converting copy constructor. "explicit" only if
435   // std::is_convertible<const U&, T>::value is false. It is implemented by
436   // declaring two almost same constructors, but that condition in enable_if_t
437   // is different, so that either one is chosen, thanks to SFINAE.
438   template <typename U,
439             typename std::enable_if<
440                 std::is_constructible<T, const U&>::value &&
441                     !internal::IsConvertibleFromOptional<T, U>::value &&
442                     std::is_convertible<const U&, T>::value,
443                 bool>::type = false>
444   Optional(const Optional<U>& other) : internal::OptionalBase<T>(other) {}
445 
446   template <typename U,
447             typename std::enable_if<
448                 std::is_constructible<T, const U&>::value &&
449                     !internal::IsConvertibleFromOptional<T, U>::value &&
450                     !std::is_convertible<const U&, T>::value,
451                 bool>::type = false>
452   explicit Optional(const Optional<U>& other)
453       : internal::OptionalBase<T>(other) {}
454 
455   // Converting move constructor. Similar to converting copy constructor,
456   // declaring two (explicit and non-explicit) constructors.
457   template <typename U,
458             typename std::enable_if<
459                 std::is_constructible<T, U&&>::value &&
460                     !internal::IsConvertibleFromOptional<T, U>::value &&
461                     std::is_convertible<U&&, T>::value,
462                 bool>::type = false>
463   Optional(Optional<U>&& other) : internal::OptionalBase<T>(std::move(other)) {}
464 
465   template <typename U,
466             typename std::enable_if<
467                 std::is_constructible<T, U&&>::value &&
468                     !internal::IsConvertibleFromOptional<T, U>::value &&
469                     !std::is_convertible<U&&, T>::value,
470                 bool>::type = false>
471   explicit Optional(Optional<U>&& other)
472       : internal::OptionalBase<T>(std::move(other)) {}
473 
474   template <class... Args>
475   constexpr explicit Optional(in_place_t, Args&&... args)
476       : internal::OptionalBase<T>(in_place, std::forward<Args>(args)...) {}
477 
478   template <class U,
479             class... Args,
480             class = typename std::enable_if<
481                 std::is_constructible<value_type,
482                                       std::initializer_list<U>&,
483                                       Args...>::value>::type>
484   constexpr explicit Optional(in_place_t,
485                               std::initializer_list<U> il,
486                               Args&&... args)
487       : internal::OptionalBase<T>(in_place, il, std::forward<Args>(args)...) {}
488 
489   // Forward value constructor. Similar to converting constructors,
490   // conditionally explicit.
491   template <
492       typename U = value_type,
493       typename std::enable_if<
494           std::is_constructible<T, U&&>::value &&
495               !std::is_same<internal::RemoveCvRefT<U>, in_place_t>::value &&
496               !std::is_same<internal::RemoveCvRefT<U>, Optional<T>>::value &&
497               std::is_convertible<U&&, T>::value,
498           bool>::type = false>
499   constexpr Optional(U&& value)
500       : internal::OptionalBase<T>(in_place, std::forward<U>(value)) {}
501 
502   template <
503       typename U = value_type,
504       typename std::enable_if<
505           std::is_constructible<T, U&&>::value &&
506               !std::is_same<internal::RemoveCvRefT<U>, in_place_t>::value &&
507               !std::is_same<internal::RemoveCvRefT<U>, Optional<T>>::value &&
508               !std::is_convertible<U&&, T>::value,
509           bool>::type = false>
510   constexpr explicit Optional(U&& value)
511       : internal::OptionalBase<T>(in_place, std::forward<U>(value)) {}
512 
513   ~Optional() = default;
514 
515   // Defer copy-/move- assign operator implementation to OptionalBase.
516   Optional& operator=(const Optional& other) = default;
517   Optional& operator=(Optional&& other) noexcept(
518       std::is_nothrow_move_assignable<T>::value&&
519           std::is_nothrow_move_constructible<T>::value) = default;
520 
521   Optional& operator=(nullopt_t) {
522     FreeIfNeeded();
523     return *this;
524   }
525 
526   // Perfect-forwarded assignment.
527   template <typename U>
528   typename std::enable_if<
529       !std::is_same<internal::RemoveCvRefT<U>, Optional<T>>::value &&
530           std::is_constructible<T, U>::value &&
531           std::is_assignable<T&, U>::value &&
532           (!std::is_scalar<T>::value ||
533            !std::is_same<typename std::decay<U>::type, T>::value),
534       Optional&>::type
535   operator=(U&& value) {
536     InitOrAssign(std::forward<U>(value));
537     return *this;
538   }
539 
540   // Copy assign the state of other.
541   template <typename U>
542   typename std::enable_if<!internal::IsAssignableFromOptional<T, U>::value &&
543                               std::is_constructible<T, const U&>::value &&
544                               std::is_assignable<T&, const U&>::value,
545                           Optional&>::type
546   operator=(const Optional<U>& other) {
547     CopyAssign(other);
548     return *this;
549   }
550 
551   // Move assign the state of other.
552   template <typename U>
553   typename std::enable_if<!internal::IsAssignableFromOptional<T, U>::value &&
554                               std::is_constructible<T, U>::value &&
555                               std::is_assignable<T&, U>::value,
556                           Optional&>::type
557   operator=(Optional<U>&& other) {
558     MoveAssign(std::move(other));
559     return *this;
560   }
561 
562   const T* operator->() const {
563     PERFETTO_DCHECK(storage_.is_populated_);
564     return &storage_.value_;
565   }
566 
567   T* operator->() {
568     PERFETTO_DCHECK(storage_.is_populated_);
569     return &storage_.value_;
570   }
571 
572   const T& operator*() const& {
573     PERFETTO_DCHECK(storage_.is_populated_);
574     return storage_.value_;
575   }
576 
577   T& operator*() & {
578     PERFETTO_DCHECK(storage_.is_populated_);
579     return storage_.value_;
580   }
581 
582   const T&& operator*() const&& {
583     PERFETTO_DCHECK(storage_.is_populated_);
584     return std::move(storage_.value_);
585   }
586 
587   T&& operator*() && {
588     PERFETTO_DCHECK(storage_.is_populated_);
589     return std::move(storage_.value_);
590   }
591 
592   constexpr explicit operator bool() const { return storage_.is_populated_; }
593 
594   constexpr bool has_value() const { return storage_.is_populated_; }
595 
596   T& value() & {
597     PERFETTO_CHECK(storage_.is_populated_);
598     return storage_.value_;
599   }
600 
601   const T& value() const& {
602     PERFETTO_CHECK(storage_.is_populated_);
603     return storage_.value_;
604   }
605 
606   T&& value() && {
607     PERFETTO_CHECK(storage_.is_populated_);
608     return std::move(storage_.value_);
609   }
610 
611   const T&& value() const&& {
612     PERFETTO_CHECK(storage_.is_populated_);
613     return std::move(storage_.value_);
614   }
615 
616   template <class U>
617   constexpr T value_or(U&& default_value) const& {
618     static_assert(std::is_convertible<U, T>::value,
619                   "U must be convertible to T");
620     return storage_.is_populated_
621                ? storage_.value_
622                : static_cast<T>(std::forward<U>(default_value));
623   }
624 
625   template <class U>
626   T value_or(U&& default_value) && {
627     static_assert(std::is_convertible<U, T>::value,
628                   "U must be convertible to T");
629     return storage_.is_populated_
630                ? std::move(storage_.value_)
631                : static_cast<T>(std::forward<U>(default_value));
632   }
633 
634   void swap(Optional& other) {
635     if (!storage_.is_populated_ && !other.storage_.is_populated_)
636       return;
637 
638     if (storage_.is_populated_ != other.storage_.is_populated_) {
639       if (storage_.is_populated_) {
640         other.storage_.Init(std::move(storage_.value_));
641         FreeIfNeeded();
642       } else {
643         storage_.Init(std::move(other.storage_.value_));
644         other.FreeIfNeeded();
645       }
646       return;
647     }
648 
649     PERFETTO_DCHECK(storage_.is_populated_ && other.storage_.is_populated_);
650     using std::swap;
651     swap(**this, *other);
652   }
653 
654   void reset() { FreeIfNeeded(); }
655 
656   template <class... Args>
657   T& emplace(Args&&... args) {
658     FreeIfNeeded();
659     storage_.Init(std::forward<Args>(args)...);
660     return storage_.value_;
661   }
662 
663   template <class U, class... Args>
664   typename std::enable_if<
665       std::is_constructible<T, std::initializer_list<U>&, Args&&...>::value,
666       T&>::type
667   emplace(std::initializer_list<U> il, Args&&... args) {
668     FreeIfNeeded();
669     storage_.Init(il, std::forward<Args>(args)...);
670     return storage_.value_;
671   }
672 
673  private:
674   // Accessing template base class's protected member needs explicit
675   // declaration to do so.
676   using internal::OptionalBase<T>::CopyAssign;
677   using internal::OptionalBase<T>::FreeIfNeeded;
678   using internal::OptionalBase<T>::InitOrAssign;
679   using internal::OptionalBase<T>::MoveAssign;
680   using internal::OptionalBase<T>::storage_;
681 };
682 
683 // Here after defines comparation operators. The definition follows
684 // http://en.cppreference.com/w/cpp/utility/optional/operator_cmp
685 // while bool() casting is replaced by has_value() to meet the chromium
686 // style guide.
687 template <class T, class U>
688 bool operator==(const Optional<T>& lhs, const Optional<U>& rhs) {
689   if (lhs.has_value() != rhs.has_value())
690     return false;
691   if (!lhs.has_value())
692     return true;
693   return *lhs == *rhs;
694 }
695 
696 template <class T, class U>
697 bool operator!=(const Optional<T>& lhs, const Optional<U>& rhs) {
698   if (lhs.has_value() != rhs.has_value())
699     return true;
700   if (!lhs.has_value())
701     return false;
702   return *lhs != *rhs;
703 }
704 
705 template <class T, class U>
706 bool operator<(const Optional<T>& lhs, const Optional<U>& rhs) {
707   if (!rhs.has_value())
708     return false;
709   if (!lhs.has_value())
710     return true;
711   return *lhs < *rhs;
712 }
713 
714 template <class T, class U>
715 bool operator<=(const Optional<T>& lhs, const Optional<U>& rhs) {
716   if (!lhs.has_value())
717     return true;
718   if (!rhs.has_value())
719     return false;
720   return *lhs <= *rhs;
721 }
722 
723 template <class T, class U>
724 bool operator>(const Optional<T>& lhs, const Optional<U>& rhs) {
725   if (!lhs.has_value())
726     return false;
727   if (!rhs.has_value())
728     return true;
729   return *lhs > *rhs;
730 }
731 
732 template <class T, class U>
733 bool operator>=(const Optional<T>& lhs, const Optional<U>& rhs) {
734   if (!rhs.has_value())
735     return true;
736   if (!lhs.has_value())
737     return false;
738   return *lhs >= *rhs;
739 }
740 
741 template <class T>
742 constexpr bool operator==(const Optional<T>& opt, nullopt_t) {
743   return !opt;
744 }
745 
746 template <class T>
747 constexpr bool operator==(nullopt_t, const Optional<T>& opt) {
748   return !opt;
749 }
750 
751 template <class T>
752 constexpr bool operator!=(const Optional<T>& opt, nullopt_t) {
753   return opt.has_value();
754 }
755 
756 template <class T>
757 constexpr bool operator!=(nullopt_t, const Optional<T>& opt) {
758   return opt.has_value();
759 }
760 
761 template <class T>
762 constexpr bool operator<(const Optional<T>&, nullopt_t) {
763   return false;
764 }
765 
766 template <class T>
767 constexpr bool operator<(nullopt_t, const Optional<T>& opt) {
768   return opt.has_value();
769 }
770 
771 template <class T>
772 constexpr bool operator<=(const Optional<T>& opt, nullopt_t) {
773   return !opt;
774 }
775 
776 template <class T>
777 constexpr bool operator<=(nullopt_t, const Optional<T>&) {
778   return true;
779 }
780 
781 template <class T>
782 constexpr bool operator>(const Optional<T>& opt, nullopt_t) {
783   return opt.has_value();
784 }
785 
786 template <class T>
787 constexpr bool operator>(nullopt_t, const Optional<T>&) {
788   return false;
789 }
790 
791 template <class T>
792 constexpr bool operator>=(const Optional<T>&, nullopt_t) {
793   return true;
794 }
795 
796 template <class T>
797 constexpr bool operator>=(nullopt_t, const Optional<T>& opt) {
798   return !opt;
799 }
800 
801 template <class T, class U>
802 constexpr bool operator==(const Optional<T>& opt, const U& value) {
803   return opt.has_value() ? *opt == value : false;
804 }
805 
806 template <class T, class U>
807 constexpr bool operator==(const U& value, const Optional<T>& opt) {
808   return opt.has_value() ? value == *opt : false;
809 }
810 
811 template <class T, class U>
812 constexpr bool operator!=(const Optional<T>& opt, const U& value) {
813   return opt.has_value() ? *opt != value : true;
814 }
815 
816 template <class T, class U>
817 constexpr bool operator!=(const U& value, const Optional<T>& opt) {
818   return opt.has_value() ? value != *opt : true;
819 }
820 
821 template <class T, class U>
822 constexpr bool operator<(const Optional<T>& opt, const U& value) {
823   return opt.has_value() ? *opt < value : true;
824 }
825 
826 template <class T, class U>
827 constexpr bool operator<(const U& value, const Optional<T>& opt) {
828   return opt.has_value() ? value < *opt : false;
829 }
830 
831 template <class T, class U>
832 constexpr bool operator<=(const Optional<T>& opt, const U& value) {
833   return opt.has_value() ? *opt <= value : true;
834 }
835 
836 template <class T, class U>
837 constexpr bool operator<=(const U& value, const Optional<T>& opt) {
838   return opt.has_value() ? value <= *opt : false;
839 }
840 
841 template <class T, class U>
842 constexpr bool operator>(const Optional<T>& opt, const U& value) {
843   return opt.has_value() ? *opt > value : false;
844 }
845 
846 template <class T, class U>
847 constexpr bool operator>(const U& value, const Optional<T>& opt) {
848   return opt.has_value() ? value > *opt : true;
849 }
850 
851 template <class T, class U>
852 constexpr bool operator>=(const Optional<T>& opt, const U& value) {
853   return opt.has_value() ? *opt >= value : false;
854 }
855 
856 template <class T, class U>
857 constexpr bool operator>=(const U& value, const Optional<T>& opt) {
858   return opt.has_value() ? value >= *opt : true;
859 }
860 
861 template <class T>
862 constexpr Optional<typename std::decay<T>::type> make_optional(T&& value) {
863   return Optional<typename std::decay<T>::type>(std::forward<T>(value));
864 }
865 
866 template <class T, class... Args>
867 constexpr Optional<T> make_optional(Args&&... args) {
868   return Optional<T>(in_place, std::forward<Args>(args)...);
869 }
870 
871 template <class T, class U, class... Args>
872 constexpr Optional<T> make_optional(std::initializer_list<U> il,
873                                     Args&&... args) {
874   return Optional<T>(in_place, il, std::forward<Args>(args)...);
875 }
876 
877 // Partial specialization for a function template is not allowed. Also, it is
878 // not allowed to add overload function to std namespace, while it is allowed
879 // to specialize the template in std. Thus, swap() (kind of) overloading is
880 // defined in base namespace, instead.
881 template <class T>
882 typename std::enable_if<std::is_move_constructible<T>::value &&
883                         internal::IsSwappable<T>::value>::type
884 swap(Optional<T>& lhs, Optional<T>& rhs) {
885   lhs.swap(rhs);
886 }
887 
888 }  // namespace base
889 }  // namespace perfetto
890 
891 template <class T>
892 struct std::hash<perfetto::base::Optional<T>> {
893   size_t operator()(const perfetto::base::Optional<T>& opt) const {
894     return opt == perfetto::base::nullopt ? 0 : std::hash<T>()(*opt);
895   }
896 };
897 
898 #endif  // INCLUDE_PERFETTO_EXT_BASE_OPTIONAL_H_
899