11cb0ef41Sopenharmony_ci// Copyright 2016 The Chromium Authors. All rights reserved.
21cb0ef41Sopenharmony_ci// Use of this source code is governed by a BSD-style license that can be
31cb0ef41Sopenharmony_ci// found in the LICENSE file.
41cb0ef41Sopenharmony_ci
51cb0ef41Sopenharmony_ci// This file is a clone of "base/optional.h" in chromium.
61cb0ef41Sopenharmony_ci// Keep in sync, especially when fixing bugs.
71cb0ef41Sopenharmony_ci// Copyright 2017 the V8 project authors. All rights reserved.
81cb0ef41Sopenharmony_ci
91cb0ef41Sopenharmony_ci#ifndef V8_BASE_OPTIONAL_H_
101cb0ef41Sopenharmony_ci#define V8_BASE_OPTIONAL_H_
111cb0ef41Sopenharmony_ci
121cb0ef41Sopenharmony_ci#include <type_traits>
131cb0ef41Sopenharmony_ci#include <utility>
141cb0ef41Sopenharmony_ci
151cb0ef41Sopenharmony_ci#include "src/base/logging.h"
161cb0ef41Sopenharmony_ci
171cb0ef41Sopenharmony_cinamespace v8 {
181cb0ef41Sopenharmony_cinamespace base {
191cb0ef41Sopenharmony_ci
201cb0ef41Sopenharmony_ci// Specification:
211cb0ef41Sopenharmony_ci// http://en.cppreference.com/w/cpp/utility/optional/in_place_t
221cb0ef41Sopenharmony_cistruct in_place_t {};
231cb0ef41Sopenharmony_ci
241cb0ef41Sopenharmony_ci// Specification:
251cb0ef41Sopenharmony_ci// http://en.cppreference.com/w/cpp/utility/optional/nullopt_t
261cb0ef41Sopenharmony_cistruct nullopt_t {
271cb0ef41Sopenharmony_ci  constexpr explicit nullopt_t(int) {}
281cb0ef41Sopenharmony_ci};
291cb0ef41Sopenharmony_ci
301cb0ef41Sopenharmony_ci// Specification:
311cb0ef41Sopenharmony_ci// http://en.cppreference.com/w/cpp/utility/optional/in_place
321cb0ef41Sopenharmony_ciconstexpr in_place_t in_place = {};
331cb0ef41Sopenharmony_ci
341cb0ef41Sopenharmony_ci// Specification:
351cb0ef41Sopenharmony_ci// http://en.cppreference.com/w/cpp/utility/optional/nullopt
361cb0ef41Sopenharmony_ciconstexpr nullopt_t nullopt(0);
371cb0ef41Sopenharmony_ci
381cb0ef41Sopenharmony_ci// Forward declaration, which is referred by following helpers.
391cb0ef41Sopenharmony_citemplate <typename T>
401cb0ef41Sopenharmony_ciclass Optional;
411cb0ef41Sopenharmony_ci
421cb0ef41Sopenharmony_cinamespace internal {
431cb0ef41Sopenharmony_ci
441cb0ef41Sopenharmony_citemplate <typename T, bool = std::is_trivially_destructible<T>::value>
451cb0ef41Sopenharmony_cistruct OptionalStorageBase {
461cb0ef41Sopenharmony_ci  // Initializing |empty_| here instead of using default member initializing
471cb0ef41Sopenharmony_ci  // to avoid errors in g++ 4.8.
481cb0ef41Sopenharmony_ci  constexpr OptionalStorageBase() : empty_('\0') {}
491cb0ef41Sopenharmony_ci
501cb0ef41Sopenharmony_ci  template <class... Args>
511cb0ef41Sopenharmony_ci  constexpr explicit OptionalStorageBase(in_place_t, Args&&... args)
521cb0ef41Sopenharmony_ci      : is_populated_(true), value_(std::forward<Args>(args)...) {}
531cb0ef41Sopenharmony_ci
541cb0ef41Sopenharmony_ci  // When T is not trivially destructible we must call its
551cb0ef41Sopenharmony_ci  // destructor before deallocating its memory.
561cb0ef41Sopenharmony_ci  // Note that this hides the (implicitly declared) move constructor, which
571cb0ef41Sopenharmony_ci  // would be used for constexpr move constructor in OptionalStorage<T>.
581cb0ef41Sopenharmony_ci  // It is needed iff T is trivially move constructible. However, the current
591cb0ef41Sopenharmony_ci  // is_trivially_{copy,move}_constructible implementation requires
601cb0ef41Sopenharmony_ci  // is_trivially_destructible (which looks a bug, cf:
611cb0ef41Sopenharmony_ci  // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=51452 and
621cb0ef41Sopenharmony_ci  // http://cplusplus.github.io/LWG/lwg-active.html#2116), so it is not
631cb0ef41Sopenharmony_ci  // necessary for this case at the moment. Please see also the destructor
641cb0ef41Sopenharmony_ci  // comment in "is_trivially_destructible = true" specialization below.
651cb0ef41Sopenharmony_ci  ~OptionalStorageBase() {
661cb0ef41Sopenharmony_ci    if (is_populated_) value_.~T();
671cb0ef41Sopenharmony_ci  }
681cb0ef41Sopenharmony_ci
691cb0ef41Sopenharmony_ci  template <class... Args>
701cb0ef41Sopenharmony_ci  void Init(Args&&... args) {
711cb0ef41Sopenharmony_ci    DCHECK(!is_populated_);
721cb0ef41Sopenharmony_ci    ::new (&value_) T(std::forward<Args>(args)...);
731cb0ef41Sopenharmony_ci    is_populated_ = true;
741cb0ef41Sopenharmony_ci  }
751cb0ef41Sopenharmony_ci
761cb0ef41Sopenharmony_ci  bool is_populated_ = false;
771cb0ef41Sopenharmony_ci  union {
781cb0ef41Sopenharmony_ci    // |empty_| exists so that the union will always be initialized, even when
791cb0ef41Sopenharmony_ci    // it doesn't contain a value. Union members must be initialized for the
801cb0ef41Sopenharmony_ci    // constructor to be 'constexpr'.
811cb0ef41Sopenharmony_ci    char empty_;
821cb0ef41Sopenharmony_ci    T value_;
831cb0ef41Sopenharmony_ci  };
841cb0ef41Sopenharmony_ci};
851cb0ef41Sopenharmony_ci
861cb0ef41Sopenharmony_citemplate <typename T>
871cb0ef41Sopenharmony_cistruct OptionalStorageBase<T, true /* trivially destructible */> {
881cb0ef41Sopenharmony_ci  // Initializing |empty_| here instead of using default member initializing
891cb0ef41Sopenharmony_ci  // to avoid errors in g++ 4.8.
901cb0ef41Sopenharmony_ci  constexpr OptionalStorageBase() : empty_('\0') {}
911cb0ef41Sopenharmony_ci
921cb0ef41Sopenharmony_ci  template <class... Args>
931cb0ef41Sopenharmony_ci  constexpr explicit OptionalStorageBase(in_place_t, Args&&... args)
941cb0ef41Sopenharmony_ci      : is_populated_(true), value_(std::forward<Args>(args)...) {}
951cb0ef41Sopenharmony_ci
961cb0ef41Sopenharmony_ci  // When T is trivially destructible (i.e. its destructor does nothing) there
971cb0ef41Sopenharmony_ci  // is no need to call it. Implicitly defined destructor is trivial, because
981cb0ef41Sopenharmony_ci  // both members (bool and union containing only variants which are trivially
991cb0ef41Sopenharmony_ci  // destructible) are trivially destructible.
1001cb0ef41Sopenharmony_ci  // Explicitly-defaulted destructor is also trivial, but do not use it here,
1011cb0ef41Sopenharmony_ci  // because it hides the implicit move constructor. It is needed to implement
1021cb0ef41Sopenharmony_ci  // constexpr move constructor in OptionalStorage iff T is trivially move
1031cb0ef41Sopenharmony_ci  // constructible. Note that, if T is trivially move constructible, the move
1041cb0ef41Sopenharmony_ci  // constructor of OptionalStorageBase<T> is also implicitly defined and it is
1051cb0ef41Sopenharmony_ci  // trivially move constructor. If T is not trivially move constructible,
1061cb0ef41Sopenharmony_ci  // "not declaring move constructor without destructor declaration" here means
1071cb0ef41Sopenharmony_ci  // "delete move constructor", which works because any move constructor of
1081cb0ef41Sopenharmony_ci  // OptionalStorage will not refer to it in that case.
1091cb0ef41Sopenharmony_ci
1101cb0ef41Sopenharmony_ci  template <class... Args>
1111cb0ef41Sopenharmony_ci  void Init(Args&&... args) {
1121cb0ef41Sopenharmony_ci    DCHECK(!is_populated_);
1131cb0ef41Sopenharmony_ci    ::new (&value_) T(std::forward<Args>(args)...);
1141cb0ef41Sopenharmony_ci    is_populated_ = true;
1151cb0ef41Sopenharmony_ci  }
1161cb0ef41Sopenharmony_ci
1171cb0ef41Sopenharmony_ci  bool is_populated_ = false;
1181cb0ef41Sopenharmony_ci  union {
1191cb0ef41Sopenharmony_ci    // |empty_| exists so that the union will always be initialized, even when
1201cb0ef41Sopenharmony_ci    // it doesn't contain a value. Union members must be initialized for the
1211cb0ef41Sopenharmony_ci    // constructor to be 'constexpr'.
1221cb0ef41Sopenharmony_ci    char empty_;
1231cb0ef41Sopenharmony_ci    T value_;
1241cb0ef41Sopenharmony_ci  };
1251cb0ef41Sopenharmony_ci};
1261cb0ef41Sopenharmony_ci
1271cb0ef41Sopenharmony_ci// Implement conditional constexpr copy and move constructors. These are
1281cb0ef41Sopenharmony_ci// constexpr if is_trivially_{copy,move}_constructible<T>::value is true
1291cb0ef41Sopenharmony_ci// respectively. If each is true, the corresponding constructor is defined as
1301cb0ef41Sopenharmony_ci// "= default;", which generates a constexpr constructor (In this case,
1311cb0ef41Sopenharmony_ci// the condition of constexpr-ness is satisfied because the base class also has
1321cb0ef41Sopenharmony_ci// compiler generated constexpr {copy,move} constructors). Note that
1331cb0ef41Sopenharmony_ci// placement-new is prohibited in constexpr.
1341cb0ef41Sopenharmony_citemplate <typename T, bool = std::is_trivially_copy_constructible<T>::value,
1351cb0ef41Sopenharmony_ci          bool = std::is_trivially_move_constructible<T>::value>
1361cb0ef41Sopenharmony_cistruct OptionalStorage : OptionalStorageBase<T> {
1371cb0ef41Sopenharmony_ci  // This is no trivially {copy,move} constructible case. Other cases are
1381cb0ef41Sopenharmony_ci  // defined below as specializations.
1391cb0ef41Sopenharmony_ci
1401cb0ef41Sopenharmony_ci  // Accessing the members of template base class requires explicit
1411cb0ef41Sopenharmony_ci  // declaration.
1421cb0ef41Sopenharmony_ci  using OptionalStorageBase<T>::is_populated_;
1431cb0ef41Sopenharmony_ci  using OptionalStorageBase<T>::value_;
1441cb0ef41Sopenharmony_ci  using OptionalStorageBase<T>::Init;
1451cb0ef41Sopenharmony_ci
1461cb0ef41Sopenharmony_ci  // Inherit constructors (specifically, the in_place constructor).
1471cb0ef41Sopenharmony_ci  using OptionalStorageBase<T>::OptionalStorageBase;
1481cb0ef41Sopenharmony_ci
1491cb0ef41Sopenharmony_ci  // User defined constructor deletes the default constructor.
1501cb0ef41Sopenharmony_ci  // Define it explicitly.
1511cb0ef41Sopenharmony_ci  OptionalStorage() = default;
1521cb0ef41Sopenharmony_ci
1531cb0ef41Sopenharmony_ci  OptionalStorage(const OptionalStorage& other) V8_NOEXCEPT {
1541cb0ef41Sopenharmony_ci    if (other.is_populated_) Init(other.value_);
1551cb0ef41Sopenharmony_ci  }
1561cb0ef41Sopenharmony_ci
1571cb0ef41Sopenharmony_ci  OptionalStorage(OptionalStorage&& other) V8_NOEXCEPT {
1581cb0ef41Sopenharmony_ci    if (other.is_populated_) Init(std::move(other.value_));
1591cb0ef41Sopenharmony_ci  }
1601cb0ef41Sopenharmony_ci};
1611cb0ef41Sopenharmony_ci
1621cb0ef41Sopenharmony_citemplate <typename T>
1631cb0ef41Sopenharmony_cistruct OptionalStorage<T, true /* trivially copy constructible */,
1641cb0ef41Sopenharmony_ci                       false /* trivially move constructible */>
1651cb0ef41Sopenharmony_ci    : OptionalStorageBase<T> {
1661cb0ef41Sopenharmony_ci  using OptionalStorageBase<T>::is_populated_;
1671cb0ef41Sopenharmony_ci  using OptionalStorageBase<T>::value_;
1681cb0ef41Sopenharmony_ci  using OptionalStorageBase<T>::Init;
1691cb0ef41Sopenharmony_ci  using OptionalStorageBase<T>::OptionalStorageBase;
1701cb0ef41Sopenharmony_ci
1711cb0ef41Sopenharmony_ci  OptionalStorage() = default;
1721cb0ef41Sopenharmony_ci  OptionalStorage(const OptionalStorage& other) V8_NOEXCEPT = default;
1731cb0ef41Sopenharmony_ci
1741cb0ef41Sopenharmony_ci  OptionalStorage(OptionalStorage&& other) V8_NOEXCEPT {
1751cb0ef41Sopenharmony_ci    if (other.is_populated_) Init(std::move(other.value_));
1761cb0ef41Sopenharmony_ci  }
1771cb0ef41Sopenharmony_ci};
1781cb0ef41Sopenharmony_ci
1791cb0ef41Sopenharmony_citemplate <typename T>
1801cb0ef41Sopenharmony_cistruct OptionalStorage<T, false /* trivially copy constructible */,
1811cb0ef41Sopenharmony_ci                       true /* trivially move constructible */>
1821cb0ef41Sopenharmony_ci    : OptionalStorageBase<T> {
1831cb0ef41Sopenharmony_ci  using OptionalStorageBase<T>::is_populated_;
1841cb0ef41Sopenharmony_ci  using OptionalStorageBase<T>::value_;
1851cb0ef41Sopenharmony_ci  using OptionalStorageBase<T>::Init;
1861cb0ef41Sopenharmony_ci  using OptionalStorageBase<T>::OptionalStorageBase;
1871cb0ef41Sopenharmony_ci
1881cb0ef41Sopenharmony_ci  OptionalStorage() = default;
1891cb0ef41Sopenharmony_ci  OptionalStorage(OptionalStorage&& other) V8_NOEXCEPT = default;
1901cb0ef41Sopenharmony_ci
1911cb0ef41Sopenharmony_ci  OptionalStorage(const OptionalStorage& other) V8_NOEXCEPT {
1921cb0ef41Sopenharmony_ci    if (other.is_populated_) Init(other.value_);
1931cb0ef41Sopenharmony_ci  }
1941cb0ef41Sopenharmony_ci};
1951cb0ef41Sopenharmony_ci
1961cb0ef41Sopenharmony_citemplate <typename T>
1971cb0ef41Sopenharmony_cistruct OptionalStorage<T, true /* trivially copy constructible */,
1981cb0ef41Sopenharmony_ci                       true /* trivially move constructible */>
1991cb0ef41Sopenharmony_ci    : OptionalStorageBase<T> {
2001cb0ef41Sopenharmony_ci  // If both trivially {copy,move} constructible are true, it is not necessary
2011cb0ef41Sopenharmony_ci  // to use user-defined constructors. So, just inheriting constructors
2021cb0ef41Sopenharmony_ci  // from the base class works.
2031cb0ef41Sopenharmony_ci  using OptionalStorageBase<T>::OptionalStorageBase;
2041cb0ef41Sopenharmony_ci};
2051cb0ef41Sopenharmony_ci
2061cb0ef41Sopenharmony_ci// Base class to support conditionally usable copy-/move- constructors
2071cb0ef41Sopenharmony_ci// and assign operators.
2081cb0ef41Sopenharmony_citemplate <typename T>
2091cb0ef41Sopenharmony_ciclass OptionalBase {
2101cb0ef41Sopenharmony_ci  // This class provides implementation rather than public API, so everything
2111cb0ef41Sopenharmony_ci  // should be hidden. Often we use composition, but we cannot in this case
2121cb0ef41Sopenharmony_ci  // because of C++ language restriction.
2131cb0ef41Sopenharmony_ci protected:
2141cb0ef41Sopenharmony_ci  constexpr OptionalBase() = default;
2151cb0ef41Sopenharmony_ci  constexpr OptionalBase(const OptionalBase& other) V8_NOEXCEPT = default;
2161cb0ef41Sopenharmony_ci  constexpr OptionalBase(OptionalBase&& other) V8_NOEXCEPT = default;
2171cb0ef41Sopenharmony_ci
2181cb0ef41Sopenharmony_ci  template <class... Args>
2191cb0ef41Sopenharmony_ci  constexpr explicit OptionalBase(in_place_t, Args&&... args)
2201cb0ef41Sopenharmony_ci      : storage_(in_place, std::forward<Args>(args)...) {}
2211cb0ef41Sopenharmony_ci
2221cb0ef41Sopenharmony_ci  // Implementation of converting constructors.
2231cb0ef41Sopenharmony_ci  template <typename U>
2241cb0ef41Sopenharmony_ci  explicit OptionalBase(const OptionalBase<U>& other) V8_NOEXCEPT {
2251cb0ef41Sopenharmony_ci    if (other.storage_.is_populated_) storage_.Init(other.storage_.value_);
2261cb0ef41Sopenharmony_ci  }
2271cb0ef41Sopenharmony_ci
2281cb0ef41Sopenharmony_ci  template <typename U>
2291cb0ef41Sopenharmony_ci  explicit OptionalBase(OptionalBase<U>&& other) V8_NOEXCEPT {
2301cb0ef41Sopenharmony_ci    if (other.storage_.is_populated_)
2311cb0ef41Sopenharmony_ci      storage_.Init(std::move(other.storage_.value_));
2321cb0ef41Sopenharmony_ci  }
2331cb0ef41Sopenharmony_ci
2341cb0ef41Sopenharmony_ci  ~OptionalBase() = default;
2351cb0ef41Sopenharmony_ci
2361cb0ef41Sopenharmony_ci  OptionalBase& operator=(const OptionalBase& other) V8_NOEXCEPT {
2371cb0ef41Sopenharmony_ci    CopyAssign(other);
2381cb0ef41Sopenharmony_ci    return *this;
2391cb0ef41Sopenharmony_ci  }
2401cb0ef41Sopenharmony_ci
2411cb0ef41Sopenharmony_ci  OptionalBase& operator=(OptionalBase&& other) V8_NOEXCEPT {
2421cb0ef41Sopenharmony_ci    MoveAssign(std::move(other));
2431cb0ef41Sopenharmony_ci    return *this;
2441cb0ef41Sopenharmony_ci  }
2451cb0ef41Sopenharmony_ci
2461cb0ef41Sopenharmony_ci  template <typename U>
2471cb0ef41Sopenharmony_ci  void CopyAssign(const OptionalBase<U>& other) {
2481cb0ef41Sopenharmony_ci    if (other.storage_.is_populated_)
2491cb0ef41Sopenharmony_ci      InitOrAssign(other.storage_.value_);
2501cb0ef41Sopenharmony_ci    else
2511cb0ef41Sopenharmony_ci      FreeIfNeeded();
2521cb0ef41Sopenharmony_ci  }
2531cb0ef41Sopenharmony_ci
2541cb0ef41Sopenharmony_ci  template <typename U>
2551cb0ef41Sopenharmony_ci  void MoveAssign(OptionalBase<U>&& other) {
2561cb0ef41Sopenharmony_ci    if (other.storage_.is_populated_)
2571cb0ef41Sopenharmony_ci      InitOrAssign(std::move(other.storage_.value_));
2581cb0ef41Sopenharmony_ci    else
2591cb0ef41Sopenharmony_ci      FreeIfNeeded();
2601cb0ef41Sopenharmony_ci  }
2611cb0ef41Sopenharmony_ci
2621cb0ef41Sopenharmony_ci  template <typename U>
2631cb0ef41Sopenharmony_ci  void InitOrAssign(U&& value) {
2641cb0ef41Sopenharmony_ci    if (storage_.is_populated_)
2651cb0ef41Sopenharmony_ci      storage_.value_ = std::forward<U>(value);
2661cb0ef41Sopenharmony_ci    else
2671cb0ef41Sopenharmony_ci      storage_.Init(std::forward<U>(value));
2681cb0ef41Sopenharmony_ci  }
2691cb0ef41Sopenharmony_ci
2701cb0ef41Sopenharmony_ci  void FreeIfNeeded() {
2711cb0ef41Sopenharmony_ci    if (!storage_.is_populated_) return;
2721cb0ef41Sopenharmony_ci    storage_.value_.~T();
2731cb0ef41Sopenharmony_ci    storage_.is_populated_ = false;
2741cb0ef41Sopenharmony_ci  }
2751cb0ef41Sopenharmony_ci
2761cb0ef41Sopenharmony_ci  // For implementing conversion, allow access to other typed OptionalBase
2771cb0ef41Sopenharmony_ci  // class.
2781cb0ef41Sopenharmony_ci  template <typename U>
2791cb0ef41Sopenharmony_ci  friend class OptionalBase;
2801cb0ef41Sopenharmony_ci
2811cb0ef41Sopenharmony_ci  OptionalStorage<T> storage_;
2821cb0ef41Sopenharmony_ci};
2831cb0ef41Sopenharmony_ci
2841cb0ef41Sopenharmony_ci// The following {Copy,Move}{Constructible,Assignable} structs are helpers to
2851cb0ef41Sopenharmony_ci// implement constructor/assign-operator overloading. Specifically, if T is
2861cb0ef41Sopenharmony_ci// is not movable but copyable, Optional<T>'s move constructor should not
2871cb0ef41Sopenharmony_ci// participate in overload resolution. This inheritance trick implements that.
2881cb0ef41Sopenharmony_citemplate <bool is_copy_constructible>
2891cb0ef41Sopenharmony_cistruct CopyConstructible {};
2901cb0ef41Sopenharmony_ci
2911cb0ef41Sopenharmony_citemplate <>
2921cb0ef41Sopenharmony_cistruct CopyConstructible<false> {
2931cb0ef41Sopenharmony_ci  constexpr CopyConstructible() = default;
2941cb0ef41Sopenharmony_ci  constexpr CopyConstructible(const CopyConstructible&) V8_NOEXCEPT = delete;
2951cb0ef41Sopenharmony_ci  constexpr CopyConstructible(CopyConstructible&&) V8_NOEXCEPT = default;
2961cb0ef41Sopenharmony_ci  CopyConstructible& operator=(const CopyConstructible&) V8_NOEXCEPT = default;
2971cb0ef41Sopenharmony_ci  CopyConstructible& operator=(CopyConstructible&&) V8_NOEXCEPT = default;
2981cb0ef41Sopenharmony_ci};
2991cb0ef41Sopenharmony_ci
3001cb0ef41Sopenharmony_citemplate <bool is_move_constructible>
3011cb0ef41Sopenharmony_cistruct MoveConstructible {};
3021cb0ef41Sopenharmony_ci
3031cb0ef41Sopenharmony_citemplate <>
3041cb0ef41Sopenharmony_cistruct MoveConstructible<false> {
3051cb0ef41Sopenharmony_ci  constexpr MoveConstructible() = default;
3061cb0ef41Sopenharmony_ci  constexpr MoveConstructible(const MoveConstructible&) V8_NOEXCEPT = default;
3071cb0ef41Sopenharmony_ci  constexpr MoveConstructible(MoveConstructible&&) V8_NOEXCEPT = delete;
3081cb0ef41Sopenharmony_ci  MoveConstructible& operator=(const MoveConstructible&) V8_NOEXCEPT = default;
3091cb0ef41Sopenharmony_ci  MoveConstructible& operator=(MoveConstructible&&) V8_NOEXCEPT = default;
3101cb0ef41Sopenharmony_ci};
3111cb0ef41Sopenharmony_ci
3121cb0ef41Sopenharmony_citemplate <bool is_copy_assignable>
3131cb0ef41Sopenharmony_cistruct CopyAssignable {};
3141cb0ef41Sopenharmony_ci
3151cb0ef41Sopenharmony_citemplate <>
3161cb0ef41Sopenharmony_cistruct CopyAssignable<false> {
3171cb0ef41Sopenharmony_ci  constexpr CopyAssignable() = default;
3181cb0ef41Sopenharmony_ci  constexpr CopyAssignable(const CopyAssignable&) V8_NOEXCEPT = default;
3191cb0ef41Sopenharmony_ci  constexpr CopyAssignable(CopyAssignable&&) V8_NOEXCEPT = default;
3201cb0ef41Sopenharmony_ci  CopyAssignable& operator=(const CopyAssignable&) V8_NOEXCEPT = delete;
3211cb0ef41Sopenharmony_ci  CopyAssignable& operator=(CopyAssignable&&) V8_NOEXCEPT = default;
3221cb0ef41Sopenharmony_ci};
3231cb0ef41Sopenharmony_ci
3241cb0ef41Sopenharmony_citemplate <bool is_move_assignable>
3251cb0ef41Sopenharmony_cistruct MoveAssignable {};
3261cb0ef41Sopenharmony_ci
3271cb0ef41Sopenharmony_citemplate <>
3281cb0ef41Sopenharmony_cistruct MoveAssignable<false> {
3291cb0ef41Sopenharmony_ci  constexpr MoveAssignable() = default;
3301cb0ef41Sopenharmony_ci  constexpr MoveAssignable(const MoveAssignable&) V8_NOEXCEPT = default;
3311cb0ef41Sopenharmony_ci  constexpr MoveAssignable(MoveAssignable&&) V8_NOEXCEPT = default;
3321cb0ef41Sopenharmony_ci  MoveAssignable& operator=(const MoveAssignable&) V8_NOEXCEPT = default;
3331cb0ef41Sopenharmony_ci  MoveAssignable& operator=(MoveAssignable&&) V8_NOEXCEPT = delete;
3341cb0ef41Sopenharmony_ci};
3351cb0ef41Sopenharmony_ci
3361cb0ef41Sopenharmony_ci// Helper to conditionally enable converting constructors and assign operators.
3371cb0ef41Sopenharmony_citemplate <typename T, typename U>
3381cb0ef41Sopenharmony_cistruct IsConvertibleFromOptional
3391cb0ef41Sopenharmony_ci    : std::integral_constant<
3401cb0ef41Sopenharmony_ci          bool, std::is_constructible<T, Optional<U>&>::value ||
3411cb0ef41Sopenharmony_ci                    std::is_constructible<T, const Optional<U>&>::value ||
3421cb0ef41Sopenharmony_ci                    std::is_constructible<T, Optional<U>&&>::value ||
3431cb0ef41Sopenharmony_ci                    std::is_constructible<T, const Optional<U>&&>::value ||
3441cb0ef41Sopenharmony_ci                    std::is_convertible<Optional<U>&, T>::value ||
3451cb0ef41Sopenharmony_ci                    std::is_convertible<const Optional<U>&, T>::value ||
3461cb0ef41Sopenharmony_ci                    std::is_convertible<Optional<U>&&, T>::value ||
3471cb0ef41Sopenharmony_ci                    std::is_convertible<const Optional<U>&&, T>::value> {};
3481cb0ef41Sopenharmony_ci
3491cb0ef41Sopenharmony_citemplate <typename T, typename U>
3501cb0ef41Sopenharmony_cistruct IsAssignableFromOptional
3511cb0ef41Sopenharmony_ci    : std::integral_constant<
3521cb0ef41Sopenharmony_ci          bool, IsConvertibleFromOptional<T, U>::value ||
3531cb0ef41Sopenharmony_ci                    std::is_assignable<T&, Optional<U>&>::value ||
3541cb0ef41Sopenharmony_ci                    std::is_assignable<T&, const Optional<U>&>::value ||
3551cb0ef41Sopenharmony_ci                    std::is_assignable<T&, Optional<U>&&>::value ||
3561cb0ef41Sopenharmony_ci                    std::is_assignable<T&, const Optional<U>&&>::value> {};
3571cb0ef41Sopenharmony_ci
3581cb0ef41Sopenharmony_ci// Forward compatibility for C++17.
3591cb0ef41Sopenharmony_ci// Introduce one more deeper nested namespace to avoid leaking using std::swap.
3601cb0ef41Sopenharmony_cinamespace swappable_impl {
3611cb0ef41Sopenharmony_ciusing std::swap;
3621cb0ef41Sopenharmony_ci
3631cb0ef41Sopenharmony_cistruct IsSwappableImpl {
3641cb0ef41Sopenharmony_ci  // Tests if swap can be called. Check<T&>(0) returns true_type iff swap
3651cb0ef41Sopenharmony_ci  // is available for T. Otherwise, Check's overload resolution falls back
3661cb0ef41Sopenharmony_ci  // to Check(...) declared below thanks to SFINAE, so returns false_type.
3671cb0ef41Sopenharmony_ci  template <typename T>
3681cb0ef41Sopenharmony_ci  static auto Check(int i)
3691cb0ef41Sopenharmony_ci      -> decltype(swap(std::declval<T>(), std::declval<T>()), std::true_type());
3701cb0ef41Sopenharmony_ci
3711cb0ef41Sopenharmony_ci  template <typename T>
3721cb0ef41Sopenharmony_ci  static std::false_type Check(...);
3731cb0ef41Sopenharmony_ci};
3741cb0ef41Sopenharmony_ci}  // namespace swappable_impl
3751cb0ef41Sopenharmony_ci
3761cb0ef41Sopenharmony_citemplate <typename T>
3771cb0ef41Sopenharmony_cistruct IsSwappable : decltype(swappable_impl::IsSwappableImpl::Check<T&>(0)) {};
3781cb0ef41Sopenharmony_ci
3791cb0ef41Sopenharmony_ci// Forward compatibility for C++20.
3801cb0ef41Sopenharmony_citemplate <typename T>
3811cb0ef41Sopenharmony_ciusing RemoveCvRefT =
3821cb0ef41Sopenharmony_ci    typename std::remove_cv<typename std::remove_reference<T>::type>::type;
3831cb0ef41Sopenharmony_ci
3841cb0ef41Sopenharmony_ci}  // namespace internal
3851cb0ef41Sopenharmony_ci
3861cb0ef41Sopenharmony_ci// On Windows, by default, empty-base class optimization does not work,
3871cb0ef41Sopenharmony_ci// which means even if the base class is empty struct, it still consumes one
3881cb0ef41Sopenharmony_ci// byte for its body. __declspec(empty_bases) enables the optimization.
3891cb0ef41Sopenharmony_ci// cf)
3901cb0ef41Sopenharmony_ci// https://blogs.msdn.microsoft.com/vcblog/2016/03/30/optimizing-the-layout-of-empty-base-classes-in-vs2015-update-2-3/
3911cb0ef41Sopenharmony_ci#ifdef OS_WIN
3921cb0ef41Sopenharmony_ci#define OPTIONAL_DECLSPEC_EMPTY_BASES __declspec(empty_bases)
3931cb0ef41Sopenharmony_ci#else
3941cb0ef41Sopenharmony_ci#define OPTIONAL_DECLSPEC_EMPTY_BASES
3951cb0ef41Sopenharmony_ci#endif
3961cb0ef41Sopenharmony_ci
3971cb0ef41Sopenharmony_ci// base::Optional is a Chromium version of the C++17 optional class:
3981cb0ef41Sopenharmony_ci// std::optional documentation:
3991cb0ef41Sopenharmony_ci// http://en.cppreference.com/w/cpp/utility/optional
4001cb0ef41Sopenharmony_ci// Chromium documentation:
4011cb0ef41Sopenharmony_ci// https://chromium.googlesource.com/chromium/src/+/master/docs/optional.md
4021cb0ef41Sopenharmony_ci//
4031cb0ef41Sopenharmony_ci// These are the differences between the specification and the implementation:
4041cb0ef41Sopenharmony_ci// - Constructors do not use 'constexpr' as it is a C++14 extension.
4051cb0ef41Sopenharmony_ci// - 'constexpr' might be missing in some places for reasons specified locally.
4061cb0ef41Sopenharmony_ci// - No exceptions are thrown, because they are banned from Chromium.
4071cb0ef41Sopenharmony_ci//   All copy/move constructors or assignment operators are marked V8_NOEXCEPT.
4081cb0ef41Sopenharmony_ci// - All the non-members are in the 'base' namespace instead of 'std'.
4091cb0ef41Sopenharmony_ci//
4101cb0ef41Sopenharmony_ci// Note that T cannot have a constructor T(Optional<T>) etc. Optional<T> checks
4111cb0ef41Sopenharmony_ci// T's constructor (specifically via IsConvertibleFromOptional), and in the
4121cb0ef41Sopenharmony_ci// check whether T can be constructible from Optional<T>, which is recursive
4131cb0ef41Sopenharmony_ci// so it does not work. As of Feb 2018, std::optional C++17 implementation in
4141cb0ef41Sopenharmony_ci// both clang and gcc has same limitation. MSVC SFINAE looks to have different
4151cb0ef41Sopenharmony_ci// behavior, but anyway it reports an error, too.
4161cb0ef41Sopenharmony_citemplate <typename T>
4171cb0ef41Sopenharmony_ciclass OPTIONAL_DECLSPEC_EMPTY_BASES Optional
4181cb0ef41Sopenharmony_ci    : public internal::OptionalBase<T>,
4191cb0ef41Sopenharmony_ci      public internal::CopyConstructible<std::is_copy_constructible<T>::value>,
4201cb0ef41Sopenharmony_ci      public internal::MoveConstructible<std::is_move_constructible<T>::value>,
4211cb0ef41Sopenharmony_ci      public internal::CopyAssignable<std::is_copy_constructible<T>::value &&
4221cb0ef41Sopenharmony_ci                                      std::is_copy_assignable<T>::value>,
4231cb0ef41Sopenharmony_ci      public internal::MoveAssignable<std::is_move_constructible<T>::value &&
4241cb0ef41Sopenharmony_ci                                      std::is_move_assignable<T>::value> {
4251cb0ef41Sopenharmony_ci public:
4261cb0ef41Sopenharmony_ci#undef OPTIONAL_DECLSPEC_EMPTY_BASES
4271cb0ef41Sopenharmony_ci  using value_type = T;
4281cb0ef41Sopenharmony_ci
4291cb0ef41Sopenharmony_ci  // Defer default/copy/move constructor implementation to OptionalBase.
4301cb0ef41Sopenharmony_ci  constexpr Optional() = default;
4311cb0ef41Sopenharmony_ci  constexpr Optional(const Optional& other) V8_NOEXCEPT = default;
4321cb0ef41Sopenharmony_ci  constexpr Optional(Optional&& other) V8_NOEXCEPT = default;
4331cb0ef41Sopenharmony_ci
4341cb0ef41Sopenharmony_ci  constexpr Optional(nullopt_t) {}  // NOLINT(runtime/explicit)
4351cb0ef41Sopenharmony_ci
4361cb0ef41Sopenharmony_ci  // Converting copy constructor. "explicit" only if
4371cb0ef41Sopenharmony_ci  // std::is_convertible<const U&, T>::value is false. It is implemented by
4381cb0ef41Sopenharmony_ci  // declaring two almost same constructors, but that condition in enable_if
4391cb0ef41Sopenharmony_ci  // is different, so that either one is chosen, thanks to SFINAE.
4401cb0ef41Sopenharmony_ci  template <typename U,
4411cb0ef41Sopenharmony_ci            typename std::enable_if<
4421cb0ef41Sopenharmony_ci                std::is_constructible<T, const U&>::value &&
4431cb0ef41Sopenharmony_ci                    !internal::IsConvertibleFromOptional<T, U>::value &&
4441cb0ef41Sopenharmony_ci                    std::is_convertible<const U&, T>::value,
4451cb0ef41Sopenharmony_ci                bool>::type = false>
4461cb0ef41Sopenharmony_ci  Optional(const Optional<U>& other) V8_NOEXCEPT
4471cb0ef41Sopenharmony_ci      : internal::OptionalBase<T>(other) {}
4481cb0ef41Sopenharmony_ci
4491cb0ef41Sopenharmony_ci  template <typename U,
4501cb0ef41Sopenharmony_ci            typename std::enable_if<
4511cb0ef41Sopenharmony_ci                std::is_constructible<T, const U&>::value &&
4521cb0ef41Sopenharmony_ci                    !internal::IsConvertibleFromOptional<T, U>::value &&
4531cb0ef41Sopenharmony_ci                    !std::is_convertible<const U&, T>::value,
4541cb0ef41Sopenharmony_ci                bool>::type = false>
4551cb0ef41Sopenharmony_ci  explicit Optional(const Optional<U>& other) V8_NOEXCEPT
4561cb0ef41Sopenharmony_ci      : internal::OptionalBase<T>(other) {}
4571cb0ef41Sopenharmony_ci
4581cb0ef41Sopenharmony_ci  // Converting move constructor. Similar to converting copy constructor,
4591cb0ef41Sopenharmony_ci  // declaring two (explicit and non-explicit) constructors.
4601cb0ef41Sopenharmony_ci  template <typename U,
4611cb0ef41Sopenharmony_ci            typename std::enable_if<
4621cb0ef41Sopenharmony_ci                std::is_constructible<T, U&&>::value &&
4631cb0ef41Sopenharmony_ci                    !internal::IsConvertibleFromOptional<T, U>::value &&
4641cb0ef41Sopenharmony_ci                    std::is_convertible<U&&, T>::value,
4651cb0ef41Sopenharmony_ci                bool>::type = false>
4661cb0ef41Sopenharmony_ci  Optional(Optional<U>&& other) V8_NOEXCEPT
4671cb0ef41Sopenharmony_ci      : internal::OptionalBase<T>(std::move(other)) {}
4681cb0ef41Sopenharmony_ci
4691cb0ef41Sopenharmony_ci  template <typename U,
4701cb0ef41Sopenharmony_ci            typename std::enable_if<
4711cb0ef41Sopenharmony_ci                std::is_constructible<T, U&&>::value &&
4721cb0ef41Sopenharmony_ci                    !internal::IsConvertibleFromOptional<T, U>::value &&
4731cb0ef41Sopenharmony_ci                    !std::is_convertible<U&&, T>::value,
4741cb0ef41Sopenharmony_ci                bool>::type = false>
4751cb0ef41Sopenharmony_ci  explicit Optional(Optional<U>&& other) V8_NOEXCEPT
4761cb0ef41Sopenharmony_ci      : internal::OptionalBase<T>(std::move(other)) {}
4771cb0ef41Sopenharmony_ci
4781cb0ef41Sopenharmony_ci  template <class... Args>
4791cb0ef41Sopenharmony_ci  constexpr explicit Optional(in_place_t, Args&&... args)
4801cb0ef41Sopenharmony_ci      : internal::OptionalBase<T>(in_place, std::forward<Args>(args)...) {}
4811cb0ef41Sopenharmony_ci
4821cb0ef41Sopenharmony_ci  template <class U, class... Args,
4831cb0ef41Sopenharmony_ci            class = typename std::enable_if<std::is_constructible<
4841cb0ef41Sopenharmony_ci                value_type, std::initializer_list<U>&, Args...>::value>::type>
4851cb0ef41Sopenharmony_ci  constexpr explicit Optional(in_place_t, std::initializer_list<U> il,
4861cb0ef41Sopenharmony_ci                              Args&&... args)
4871cb0ef41Sopenharmony_ci      : internal::OptionalBase<T>(in_place, il, std::forward<Args>(args)...) {}
4881cb0ef41Sopenharmony_ci
4891cb0ef41Sopenharmony_ci  // Forward value constructor. Similar to converting constructors,
4901cb0ef41Sopenharmony_ci  // conditionally explicit.
4911cb0ef41Sopenharmony_ci  template <
4921cb0ef41Sopenharmony_ci      typename U = value_type,
4931cb0ef41Sopenharmony_ci      typename std::enable_if<
4941cb0ef41Sopenharmony_ci          std::is_constructible<T, U&&>::value &&
4951cb0ef41Sopenharmony_ci              !std::is_same<internal::RemoveCvRefT<U>, in_place_t>::value &&
4961cb0ef41Sopenharmony_ci              !std::is_same<internal::RemoveCvRefT<U>, Optional<T>>::value &&
4971cb0ef41Sopenharmony_ci              std::is_convertible<U&&, T>::value,
4981cb0ef41Sopenharmony_ci          bool>::type = false>
4991cb0ef41Sopenharmony_ci  constexpr Optional(U&& value)  // NOLINT(runtime/explicit)
5001cb0ef41Sopenharmony_ci      : internal::OptionalBase<T>(in_place, std::forward<U>(value)) {}
5011cb0ef41Sopenharmony_ci
5021cb0ef41Sopenharmony_ci  template <
5031cb0ef41Sopenharmony_ci      typename U = value_type,
5041cb0ef41Sopenharmony_ci      typename std::enable_if<
5051cb0ef41Sopenharmony_ci          std::is_constructible<T, U&&>::value &&
5061cb0ef41Sopenharmony_ci              !std::is_same<internal::RemoveCvRefT<U>, in_place_t>::value &&
5071cb0ef41Sopenharmony_ci              !std::is_same<internal::RemoveCvRefT<U>, Optional<T>>::value &&
5081cb0ef41Sopenharmony_ci              !std::is_convertible<U&&, T>::value,
5091cb0ef41Sopenharmony_ci          bool>::type = false>
5101cb0ef41Sopenharmony_ci  constexpr explicit Optional(U&& value)
5111cb0ef41Sopenharmony_ci      : internal::OptionalBase<T>(in_place, std::forward<U>(value)) {}
5121cb0ef41Sopenharmony_ci
5131cb0ef41Sopenharmony_ci  ~Optional() = default;
5141cb0ef41Sopenharmony_ci
5151cb0ef41Sopenharmony_ci  // Defer copy-/move- assign operator implementation to OptionalBase.
5161cb0ef41Sopenharmony_ci  Optional& operator=(const Optional& other) V8_NOEXCEPT = default;
5171cb0ef41Sopenharmony_ci  Optional& operator=(Optional&& other) V8_NOEXCEPT = default;
5181cb0ef41Sopenharmony_ci
5191cb0ef41Sopenharmony_ci  Optional& operator=(nullopt_t) {
5201cb0ef41Sopenharmony_ci    FreeIfNeeded();
5211cb0ef41Sopenharmony_ci    return *this;
5221cb0ef41Sopenharmony_ci  }
5231cb0ef41Sopenharmony_ci
5241cb0ef41Sopenharmony_ci  // Perfect-forwarded assignment.
5251cb0ef41Sopenharmony_ci  template <typename U>
5261cb0ef41Sopenharmony_ci  typename std::enable_if<
5271cb0ef41Sopenharmony_ci      !std::is_same<internal::RemoveCvRefT<U>, Optional<T>>::value &&
5281cb0ef41Sopenharmony_ci          std::is_constructible<T, U>::value &&
5291cb0ef41Sopenharmony_ci          std::is_assignable<T&, U>::value &&
5301cb0ef41Sopenharmony_ci          (!std::is_scalar<T>::value ||
5311cb0ef41Sopenharmony_ci           !std::is_same<typename std::decay<U>::type, T>::value),
5321cb0ef41Sopenharmony_ci      Optional&>::type
5331cb0ef41Sopenharmony_ci  operator=(U&& value) V8_NOEXCEPT {
5341cb0ef41Sopenharmony_ci    InitOrAssign(std::forward<U>(value));
5351cb0ef41Sopenharmony_ci    return *this;
5361cb0ef41Sopenharmony_ci  }
5371cb0ef41Sopenharmony_ci
5381cb0ef41Sopenharmony_ci  // Copy assign the state of other.
5391cb0ef41Sopenharmony_ci  template <typename U>
5401cb0ef41Sopenharmony_ci  typename std::enable_if<!internal::IsAssignableFromOptional<T, U>::value &&
5411cb0ef41Sopenharmony_ci                              std::is_constructible<T, const U&>::value &&
5421cb0ef41Sopenharmony_ci                              std::is_assignable<T&, const U&>::value,
5431cb0ef41Sopenharmony_ci                          Optional&>::type
5441cb0ef41Sopenharmony_ci  operator=(const Optional<U>& other) V8_NOEXCEPT {
5451cb0ef41Sopenharmony_ci    CopyAssign(other);
5461cb0ef41Sopenharmony_ci    return *this;
5471cb0ef41Sopenharmony_ci  }
5481cb0ef41Sopenharmony_ci
5491cb0ef41Sopenharmony_ci  // Move assign the state of other.
5501cb0ef41Sopenharmony_ci  template <typename U>
5511cb0ef41Sopenharmony_ci  typename std::enable_if<!internal::IsAssignableFromOptional<T, U>::value &&
5521cb0ef41Sopenharmony_ci                              std::is_constructible<T, U>::value &&
5531cb0ef41Sopenharmony_ci                              std::is_assignable<T&, U>::value,
5541cb0ef41Sopenharmony_ci                          Optional&>::type
5551cb0ef41Sopenharmony_ci  operator=(Optional<U>&& other) V8_NOEXCEPT {
5561cb0ef41Sopenharmony_ci    MoveAssign(std::move(other));
5571cb0ef41Sopenharmony_ci    return *this;
5581cb0ef41Sopenharmony_ci  }
5591cb0ef41Sopenharmony_ci
5601cb0ef41Sopenharmony_ci  constexpr const T* operator->() const {
5611cb0ef41Sopenharmony_ci    DCHECK(storage_.is_populated_);
5621cb0ef41Sopenharmony_ci    return &storage_.value_;
5631cb0ef41Sopenharmony_ci  }
5641cb0ef41Sopenharmony_ci
5651cb0ef41Sopenharmony_ci  constexpr T* operator->() {
5661cb0ef41Sopenharmony_ci    DCHECK(storage_.is_populated_);
5671cb0ef41Sopenharmony_ci    return &storage_.value_;
5681cb0ef41Sopenharmony_ci  }
5691cb0ef41Sopenharmony_ci
5701cb0ef41Sopenharmony_ci  constexpr const T& operator*() const& {
5711cb0ef41Sopenharmony_ci    DCHECK(storage_.is_populated_);
5721cb0ef41Sopenharmony_ci    return storage_.value_;
5731cb0ef41Sopenharmony_ci  }
5741cb0ef41Sopenharmony_ci
5751cb0ef41Sopenharmony_ci  constexpr T& operator*() & {
5761cb0ef41Sopenharmony_ci    DCHECK(storage_.is_populated_);
5771cb0ef41Sopenharmony_ci    return storage_.value_;
5781cb0ef41Sopenharmony_ci  }
5791cb0ef41Sopenharmony_ci
5801cb0ef41Sopenharmony_ci  constexpr const T&& operator*() const&& {
5811cb0ef41Sopenharmony_ci    DCHECK(storage_.is_populated_);
5821cb0ef41Sopenharmony_ci    return std::move(storage_.value_);
5831cb0ef41Sopenharmony_ci  }
5841cb0ef41Sopenharmony_ci
5851cb0ef41Sopenharmony_ci  constexpr T&& operator*() && {
5861cb0ef41Sopenharmony_ci    DCHECK(storage_.is_populated_);
5871cb0ef41Sopenharmony_ci    return std::move(storage_.value_);
5881cb0ef41Sopenharmony_ci  }
5891cb0ef41Sopenharmony_ci
5901cb0ef41Sopenharmony_ci  constexpr explicit operator bool() const { return storage_.is_populated_; }
5911cb0ef41Sopenharmony_ci
5921cb0ef41Sopenharmony_ci  constexpr bool has_value() const { return storage_.is_populated_; }
5931cb0ef41Sopenharmony_ci
5941cb0ef41Sopenharmony_ci  T& value() & {
5951cb0ef41Sopenharmony_ci    CHECK(storage_.is_populated_);
5961cb0ef41Sopenharmony_ci    return storage_.value_;
5971cb0ef41Sopenharmony_ci  }
5981cb0ef41Sopenharmony_ci
5991cb0ef41Sopenharmony_ci  const T& value() const & {
6001cb0ef41Sopenharmony_ci    CHECK(storage_.is_populated_);
6011cb0ef41Sopenharmony_ci    return storage_.value_;
6021cb0ef41Sopenharmony_ci  }
6031cb0ef41Sopenharmony_ci
6041cb0ef41Sopenharmony_ci  T&& value() && {
6051cb0ef41Sopenharmony_ci    CHECK(storage_.is_populated_);
6061cb0ef41Sopenharmony_ci    return std::move(storage_.value_);
6071cb0ef41Sopenharmony_ci  }
6081cb0ef41Sopenharmony_ci
6091cb0ef41Sopenharmony_ci  const T&& value() const && {
6101cb0ef41Sopenharmony_ci    CHECK(storage_.is_populated_);
6111cb0ef41Sopenharmony_ci    return std::move(storage_.value_);
6121cb0ef41Sopenharmony_ci  }
6131cb0ef41Sopenharmony_ci
6141cb0ef41Sopenharmony_ci  template <class U>
6151cb0ef41Sopenharmony_ci  constexpr T value_or(U&& default_value) const & {
6161cb0ef41Sopenharmony_ci    // TODO(mlamouri): add the following assert when possible:
6171cb0ef41Sopenharmony_ci    // static_assert(std::is_copy_constructible<T>::value,
6181cb0ef41Sopenharmony_ci    //               "T must be copy constructible");
6191cb0ef41Sopenharmony_ci    static_assert(std::is_convertible<U, T>::value,
6201cb0ef41Sopenharmony_ci                  "U must be convertible to T");
6211cb0ef41Sopenharmony_ci    return storage_.is_populated_
6221cb0ef41Sopenharmony_ci               ? storage_.value_
6231cb0ef41Sopenharmony_ci               : static_cast<T>(std::forward<U>(default_value));
6241cb0ef41Sopenharmony_ci  }
6251cb0ef41Sopenharmony_ci
6261cb0ef41Sopenharmony_ci  template <class U>
6271cb0ef41Sopenharmony_ci  T value_or(U&& default_value) && {
6281cb0ef41Sopenharmony_ci    // TODO(mlamouri): add the following assert when possible:
6291cb0ef41Sopenharmony_ci    // static_assert(std::is_move_constructible<T>::value,
6301cb0ef41Sopenharmony_ci    //               "T must be move constructible");
6311cb0ef41Sopenharmony_ci    static_assert(std::is_convertible<U, T>::value,
6321cb0ef41Sopenharmony_ci                  "U must be convertible to T");
6331cb0ef41Sopenharmony_ci    return storage_.is_populated_
6341cb0ef41Sopenharmony_ci               ? std::move(storage_.value_)
6351cb0ef41Sopenharmony_ci               : static_cast<T>(std::forward<U>(default_value));
6361cb0ef41Sopenharmony_ci  }
6371cb0ef41Sopenharmony_ci
6381cb0ef41Sopenharmony_ci  void swap(Optional& other) {
6391cb0ef41Sopenharmony_ci    if (!storage_.is_populated_ && !other.storage_.is_populated_) return;
6401cb0ef41Sopenharmony_ci
6411cb0ef41Sopenharmony_ci    if (storage_.is_populated_ != other.storage_.is_populated_) {
6421cb0ef41Sopenharmony_ci      if (storage_.is_populated_) {
6431cb0ef41Sopenharmony_ci        other.storage_.Init(std::move(storage_.value_));
6441cb0ef41Sopenharmony_ci        FreeIfNeeded();
6451cb0ef41Sopenharmony_ci      } else {
6461cb0ef41Sopenharmony_ci        storage_.Init(std::move(other.storage_.value_));
6471cb0ef41Sopenharmony_ci        other.FreeIfNeeded();
6481cb0ef41Sopenharmony_ci      }
6491cb0ef41Sopenharmony_ci      return;
6501cb0ef41Sopenharmony_ci    }
6511cb0ef41Sopenharmony_ci
6521cb0ef41Sopenharmony_ci    DCHECK(storage_.is_populated_ && other.storage_.is_populated_);
6531cb0ef41Sopenharmony_ci    using std::swap;
6541cb0ef41Sopenharmony_ci    swap(**this, *other);
6551cb0ef41Sopenharmony_ci  }
6561cb0ef41Sopenharmony_ci
6571cb0ef41Sopenharmony_ci  void reset() { FreeIfNeeded(); }
6581cb0ef41Sopenharmony_ci
6591cb0ef41Sopenharmony_ci  template <class... Args>
6601cb0ef41Sopenharmony_ci  T& emplace(Args&&... args) {
6611cb0ef41Sopenharmony_ci    FreeIfNeeded();
6621cb0ef41Sopenharmony_ci    storage_.Init(std::forward<Args>(args)...);
6631cb0ef41Sopenharmony_ci    return storage_.value_;
6641cb0ef41Sopenharmony_ci  }
6651cb0ef41Sopenharmony_ci
6661cb0ef41Sopenharmony_ci  template <class U, class... Args>
6671cb0ef41Sopenharmony_ci  typename std::enable_if<
6681cb0ef41Sopenharmony_ci      std::is_constructible<T, std::initializer_list<U>&, Args&&...>::value,
6691cb0ef41Sopenharmony_ci      T&>::type
6701cb0ef41Sopenharmony_ci  emplace(std::initializer_list<U> il, Args&&... args) {
6711cb0ef41Sopenharmony_ci    FreeIfNeeded();
6721cb0ef41Sopenharmony_ci    storage_.Init(il, std::forward<Args>(args)...);
6731cb0ef41Sopenharmony_ci    return storage_.value_;
6741cb0ef41Sopenharmony_ci  }
6751cb0ef41Sopenharmony_ci
6761cb0ef41Sopenharmony_ci private:
6771cb0ef41Sopenharmony_ci  // Accessing template base class's protected member needs explicit
6781cb0ef41Sopenharmony_ci  // declaration to do so.
6791cb0ef41Sopenharmony_ci  using internal::OptionalBase<T>::CopyAssign;
6801cb0ef41Sopenharmony_ci  using internal::OptionalBase<T>::FreeIfNeeded;
6811cb0ef41Sopenharmony_ci  using internal::OptionalBase<T>::InitOrAssign;
6821cb0ef41Sopenharmony_ci  using internal::OptionalBase<T>::MoveAssign;
6831cb0ef41Sopenharmony_ci  using internal::OptionalBase<T>::storage_;
6841cb0ef41Sopenharmony_ci};
6851cb0ef41Sopenharmony_ci
6861cb0ef41Sopenharmony_ci// Here after defines comparation operators. The definition follows
6871cb0ef41Sopenharmony_ci// http://en.cppreference.com/w/cpp/utility/optional/operator_cmp
6881cb0ef41Sopenharmony_ci// while bool() casting is replaced by has_value() to meet the chromium
6891cb0ef41Sopenharmony_ci// style guide.
6901cb0ef41Sopenharmony_citemplate <class T, class U>
6911cb0ef41Sopenharmony_cibool operator==(const Optional<T>& lhs, const Optional<U>& rhs) {
6921cb0ef41Sopenharmony_ci  if (lhs.has_value() != rhs.has_value()) return false;
6931cb0ef41Sopenharmony_ci  if (!lhs.has_value()) return true;
6941cb0ef41Sopenharmony_ci  return *lhs == *rhs;
6951cb0ef41Sopenharmony_ci}
6961cb0ef41Sopenharmony_ci
6971cb0ef41Sopenharmony_citemplate <class T, class U>
6981cb0ef41Sopenharmony_cibool operator!=(const Optional<T>& lhs, const Optional<U>& rhs) {
6991cb0ef41Sopenharmony_ci  if (lhs.has_value() != rhs.has_value()) return true;
7001cb0ef41Sopenharmony_ci  if (!lhs.has_value()) return false;
7011cb0ef41Sopenharmony_ci  return *lhs != *rhs;
7021cb0ef41Sopenharmony_ci}
7031cb0ef41Sopenharmony_ci
7041cb0ef41Sopenharmony_citemplate <class T, class U>
7051cb0ef41Sopenharmony_cibool operator<(const Optional<T>& lhs, const Optional<U>& rhs) {
7061cb0ef41Sopenharmony_ci  if (!rhs.has_value()) return false;
7071cb0ef41Sopenharmony_ci  if (!lhs.has_value()) return true;
7081cb0ef41Sopenharmony_ci  return *lhs < *rhs;
7091cb0ef41Sopenharmony_ci}
7101cb0ef41Sopenharmony_ci
7111cb0ef41Sopenharmony_citemplate <class T, class U>
7121cb0ef41Sopenharmony_cibool operator<=(const Optional<T>& lhs, const Optional<U>& rhs) {
7131cb0ef41Sopenharmony_ci  if (!lhs.has_value()) return true;
7141cb0ef41Sopenharmony_ci  if (!rhs.has_value()) return false;
7151cb0ef41Sopenharmony_ci  return *lhs <= *rhs;
7161cb0ef41Sopenharmony_ci}
7171cb0ef41Sopenharmony_ci
7181cb0ef41Sopenharmony_citemplate <class T, class U>
7191cb0ef41Sopenharmony_cibool operator>(const Optional<T>& lhs, const Optional<U>& rhs) {
7201cb0ef41Sopenharmony_ci  if (!lhs.has_value()) return false;
7211cb0ef41Sopenharmony_ci  if (!rhs.has_value()) return true;
7221cb0ef41Sopenharmony_ci  return *lhs > *rhs;
7231cb0ef41Sopenharmony_ci}
7241cb0ef41Sopenharmony_ci
7251cb0ef41Sopenharmony_citemplate <class T, class U>
7261cb0ef41Sopenharmony_cibool operator>=(const Optional<T>& lhs, const Optional<U>& rhs) {
7271cb0ef41Sopenharmony_ci  if (!rhs.has_value()) return true;
7281cb0ef41Sopenharmony_ci  if (!lhs.has_value()) return false;
7291cb0ef41Sopenharmony_ci  return *lhs >= *rhs;
7301cb0ef41Sopenharmony_ci}
7311cb0ef41Sopenharmony_ci
7321cb0ef41Sopenharmony_citemplate <class T>
7331cb0ef41Sopenharmony_ciconstexpr bool operator==(const Optional<T>& opt, nullopt_t) {
7341cb0ef41Sopenharmony_ci  return !opt;
7351cb0ef41Sopenharmony_ci}
7361cb0ef41Sopenharmony_ci
7371cb0ef41Sopenharmony_citemplate <class T>
7381cb0ef41Sopenharmony_ciconstexpr bool operator==(nullopt_t, const Optional<T>& opt) {
7391cb0ef41Sopenharmony_ci  return !opt;
7401cb0ef41Sopenharmony_ci}
7411cb0ef41Sopenharmony_ci
7421cb0ef41Sopenharmony_citemplate <class T>
7431cb0ef41Sopenharmony_ciconstexpr bool operator!=(const Optional<T>& opt, nullopt_t) {
7441cb0ef41Sopenharmony_ci  return opt.has_value();
7451cb0ef41Sopenharmony_ci}
7461cb0ef41Sopenharmony_ci
7471cb0ef41Sopenharmony_citemplate <class T>
7481cb0ef41Sopenharmony_ciconstexpr bool operator!=(nullopt_t, const Optional<T>& opt) {
7491cb0ef41Sopenharmony_ci  return opt.has_value();
7501cb0ef41Sopenharmony_ci}
7511cb0ef41Sopenharmony_ci
7521cb0ef41Sopenharmony_citemplate <class T>
7531cb0ef41Sopenharmony_ciconstexpr bool operator<(const Optional<T>& opt, nullopt_t) {
7541cb0ef41Sopenharmony_ci  return false;
7551cb0ef41Sopenharmony_ci}
7561cb0ef41Sopenharmony_ci
7571cb0ef41Sopenharmony_citemplate <class T>
7581cb0ef41Sopenharmony_ciconstexpr bool operator<(nullopt_t, const Optional<T>& opt) {
7591cb0ef41Sopenharmony_ci  return opt.has_value();
7601cb0ef41Sopenharmony_ci}
7611cb0ef41Sopenharmony_ci
7621cb0ef41Sopenharmony_citemplate <class T>
7631cb0ef41Sopenharmony_ciconstexpr bool operator<=(const Optional<T>& opt, nullopt_t) {
7641cb0ef41Sopenharmony_ci  return !opt;
7651cb0ef41Sopenharmony_ci}
7661cb0ef41Sopenharmony_ci
7671cb0ef41Sopenharmony_citemplate <class T>
7681cb0ef41Sopenharmony_ciconstexpr bool operator<=(nullopt_t, const Optional<T>& opt) {
7691cb0ef41Sopenharmony_ci  return true;
7701cb0ef41Sopenharmony_ci}
7711cb0ef41Sopenharmony_ci
7721cb0ef41Sopenharmony_citemplate <class T>
7731cb0ef41Sopenharmony_ciconstexpr bool operator>(const Optional<T>& opt, nullopt_t) {
7741cb0ef41Sopenharmony_ci  return opt.has_value();
7751cb0ef41Sopenharmony_ci}
7761cb0ef41Sopenharmony_ci
7771cb0ef41Sopenharmony_citemplate <class T>
7781cb0ef41Sopenharmony_ciconstexpr bool operator>(nullopt_t, const Optional<T>& opt) {
7791cb0ef41Sopenharmony_ci  return false;
7801cb0ef41Sopenharmony_ci}
7811cb0ef41Sopenharmony_ci
7821cb0ef41Sopenharmony_citemplate <class T>
7831cb0ef41Sopenharmony_ciconstexpr bool operator>=(const Optional<T>& opt, nullopt_t) {
7841cb0ef41Sopenharmony_ci  return true;
7851cb0ef41Sopenharmony_ci}
7861cb0ef41Sopenharmony_ci
7871cb0ef41Sopenharmony_citemplate <class T>
7881cb0ef41Sopenharmony_ciconstexpr bool operator>=(nullopt_t, const Optional<T>& opt) {
7891cb0ef41Sopenharmony_ci  return !opt;
7901cb0ef41Sopenharmony_ci}
7911cb0ef41Sopenharmony_ci
7921cb0ef41Sopenharmony_citemplate <class T, class U>
7931cb0ef41Sopenharmony_ciconstexpr bool operator==(const Optional<T>& opt, const U& value) {
7941cb0ef41Sopenharmony_ci  return opt.has_value() ? *opt == value : false;
7951cb0ef41Sopenharmony_ci}
7961cb0ef41Sopenharmony_ci
7971cb0ef41Sopenharmony_citemplate <class T, class U>
7981cb0ef41Sopenharmony_ciconstexpr bool operator==(const U& value, const Optional<T>& opt) {
7991cb0ef41Sopenharmony_ci  return opt.has_value() ? value == *opt : false;
8001cb0ef41Sopenharmony_ci}
8011cb0ef41Sopenharmony_ci
8021cb0ef41Sopenharmony_citemplate <class T, class U>
8031cb0ef41Sopenharmony_ciconstexpr bool operator!=(const Optional<T>& opt, const U& value) {
8041cb0ef41Sopenharmony_ci  return opt.has_value() ? *opt != value : true;
8051cb0ef41Sopenharmony_ci}
8061cb0ef41Sopenharmony_ci
8071cb0ef41Sopenharmony_citemplate <class T, class U>
8081cb0ef41Sopenharmony_ciconstexpr bool operator!=(const U& value, const Optional<T>& opt) {
8091cb0ef41Sopenharmony_ci  return opt.has_value() ? value != *opt : true;
8101cb0ef41Sopenharmony_ci}
8111cb0ef41Sopenharmony_ci
8121cb0ef41Sopenharmony_citemplate <class T, class U>
8131cb0ef41Sopenharmony_ciconstexpr bool operator<(const Optional<T>& opt, const U& value) {
8141cb0ef41Sopenharmony_ci  return opt.has_value() ? *opt < value : true;
8151cb0ef41Sopenharmony_ci}
8161cb0ef41Sopenharmony_ci
8171cb0ef41Sopenharmony_citemplate <class T, class U>
8181cb0ef41Sopenharmony_ciconstexpr bool operator<(const U& value, const Optional<T>& opt) {
8191cb0ef41Sopenharmony_ci  return opt.has_value() ? value < *opt : false;
8201cb0ef41Sopenharmony_ci}
8211cb0ef41Sopenharmony_ci
8221cb0ef41Sopenharmony_citemplate <class T, class U>
8231cb0ef41Sopenharmony_ciconstexpr bool operator<=(const Optional<T>& opt, const U& value) {
8241cb0ef41Sopenharmony_ci  return opt.has_value() ? *opt <= value : true;
8251cb0ef41Sopenharmony_ci}
8261cb0ef41Sopenharmony_ci
8271cb0ef41Sopenharmony_citemplate <class T, class U>
8281cb0ef41Sopenharmony_ciconstexpr bool operator<=(const U& value, const Optional<T>& opt) {
8291cb0ef41Sopenharmony_ci  return opt.has_value() ? value <= *opt : false;
8301cb0ef41Sopenharmony_ci}
8311cb0ef41Sopenharmony_ci
8321cb0ef41Sopenharmony_citemplate <class T, class U>
8331cb0ef41Sopenharmony_ciconstexpr bool operator>(const Optional<T>& opt, const U& value) {
8341cb0ef41Sopenharmony_ci  return opt.has_value() ? *opt > value : false;
8351cb0ef41Sopenharmony_ci}
8361cb0ef41Sopenharmony_ci
8371cb0ef41Sopenharmony_citemplate <class T, class U>
8381cb0ef41Sopenharmony_ciconstexpr bool operator>(const U& value, const Optional<T>& opt) {
8391cb0ef41Sopenharmony_ci  return opt.has_value() ? value > *opt : true;
8401cb0ef41Sopenharmony_ci}
8411cb0ef41Sopenharmony_ci
8421cb0ef41Sopenharmony_citemplate <class T, class U>
8431cb0ef41Sopenharmony_ciconstexpr bool operator>=(const Optional<T>& opt, const U& value) {
8441cb0ef41Sopenharmony_ci  return opt.has_value() ? *opt >= value : false;
8451cb0ef41Sopenharmony_ci}
8461cb0ef41Sopenharmony_ci
8471cb0ef41Sopenharmony_citemplate <class T, class U>
8481cb0ef41Sopenharmony_ciconstexpr bool operator>=(const U& value, const Optional<T>& opt) {
8491cb0ef41Sopenharmony_ci  return opt.has_value() ? value >= *opt : true;
8501cb0ef41Sopenharmony_ci}
8511cb0ef41Sopenharmony_ci
8521cb0ef41Sopenharmony_citemplate <class T>
8531cb0ef41Sopenharmony_ciconstexpr Optional<typename std::decay<T>::type> make_optional(T&& value) {
8541cb0ef41Sopenharmony_ci  return Optional<typename std::decay<T>::type>(std::forward<T>(value));
8551cb0ef41Sopenharmony_ci}
8561cb0ef41Sopenharmony_ci
8571cb0ef41Sopenharmony_citemplate <class T, class... Args>
8581cb0ef41Sopenharmony_ciconstexpr Optional<T> make_optional(Args&&... args) {
8591cb0ef41Sopenharmony_ci  return Optional<T>(in_place, std::forward<Args>(args)...);
8601cb0ef41Sopenharmony_ci}
8611cb0ef41Sopenharmony_ci
8621cb0ef41Sopenharmony_citemplate <class T, class U, class... Args>
8631cb0ef41Sopenharmony_ciconstexpr Optional<T> make_optional(std::initializer_list<U> il,
8641cb0ef41Sopenharmony_ci                                    Args&&... args) {
8651cb0ef41Sopenharmony_ci  return Optional<T>(in_place, il, std::forward<Args>(args)...);
8661cb0ef41Sopenharmony_ci}
8671cb0ef41Sopenharmony_ci
8681cb0ef41Sopenharmony_ci// Partial specialization for a function template is not allowed. Also, it is
8691cb0ef41Sopenharmony_ci// not allowed to add overload function to std namespace, while it is allowed
8701cb0ef41Sopenharmony_ci// to specialize the template in std. Thus, swap() (kind of) overloading is
8711cb0ef41Sopenharmony_ci// defined in base namespace, instead.
8721cb0ef41Sopenharmony_citemplate <class T>
8731cb0ef41Sopenharmony_citypename std::enable_if<std::is_move_constructible<T>::value &&
8741cb0ef41Sopenharmony_ci                        internal::IsSwappable<T>::value>::type
8751cb0ef41Sopenharmony_ciswap(Optional<T>& lhs, Optional<T>& rhs) {
8761cb0ef41Sopenharmony_ci  lhs.swap(rhs);
8771cb0ef41Sopenharmony_ci}
8781cb0ef41Sopenharmony_ci
8791cb0ef41Sopenharmony_ci}  // namespace base
8801cb0ef41Sopenharmony_ci}  // namespace v8
8811cb0ef41Sopenharmony_ci
8821cb0ef41Sopenharmony_ci#endif  // V8_BASE_OPTIONAL_H_
883