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