10b57cec5SDimitry Andric// -*- C++ -*- 2349cc55cSDimitry Andric//===----------------------------------------------------------------------===// 30b57cec5SDimitry Andric// 40b57cec5SDimitry Andric// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 50b57cec5SDimitry Andric// See https://llvm.org/LICENSE.txt for license information. 60b57cec5SDimitry Andric// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 70b57cec5SDimitry Andric// 80b57cec5SDimitry Andric//===----------------------------------------------------------------------===// 90b57cec5SDimitry Andric 100b57cec5SDimitry Andric#ifndef _LIBCPP_OPTIONAL 110b57cec5SDimitry Andric#define _LIBCPP_OPTIONAL 120b57cec5SDimitry Andric 130b57cec5SDimitry Andric/* 140b57cec5SDimitry Andric optional synopsis 150b57cec5SDimitry Andric 160b57cec5SDimitry Andric// C++1z 170b57cec5SDimitry Andric 180b57cec5SDimitry Andricnamespace std { 1906c3fb27SDimitry Andric // [optional.optional], class template optional 2006c3fb27SDimitry Andric template <class T> 2106c3fb27SDimitry Andric class optional; 220b57cec5SDimitry Andric 2306c3fb27SDimitry Andric template<class T> 2406c3fb27SDimitry Andric concept is-derived-from-optional = requires(const T& t) { // exposition only 2506c3fb27SDimitry Andric []<class U>(const optional<U>&){ }(t); 2606c3fb27SDimitry Andric }; 2706c3fb27SDimitry Andric 2806c3fb27SDimitry Andric // [optional.nullopt], no-value state indicator 290b57cec5SDimitry Andric struct nullopt_t{see below }; 300b57cec5SDimitry Andric inline constexpr nullopt_t nullopt(unspecified ); 310b57cec5SDimitry Andric 3206c3fb27SDimitry Andric // [optional.bad.access], class bad_optional_access 330b57cec5SDimitry Andric class bad_optional_access; 340b57cec5SDimitry Andric 3506c3fb27SDimitry Andric // [optional.relops], relational operators 360b57cec5SDimitry Andric template <class T, class U> 370b57cec5SDimitry Andric constexpr bool operator==(const optional<T>&, const optional<U>&); 380b57cec5SDimitry Andric template <class T, class U> 390b57cec5SDimitry Andric constexpr bool operator!=(const optional<T>&, const optional<U>&); 400b57cec5SDimitry Andric template <class T, class U> 410b57cec5SDimitry Andric constexpr bool operator<(const optional<T>&, const optional<U>&); 420b57cec5SDimitry Andric template <class T, class U> 430b57cec5SDimitry Andric constexpr bool operator>(const optional<T>&, const optional<U>&); 440b57cec5SDimitry Andric template <class T, class U> 450b57cec5SDimitry Andric constexpr bool operator<=(const optional<T>&, const optional<U>&); 460b57cec5SDimitry Andric template <class T, class U> 470b57cec5SDimitry Andric constexpr bool operator>=(const optional<T>&, const optional<U>&); 4806c3fb27SDimitry Andric template<class T, three_way_comparable_with<T> U> 4906c3fb27SDimitry Andric constexpr compare_three_way_result_t<T, U> 5006c3fb27SDimitry Andric operator<=>(const optional<T>&, const optional<U>&); // since C++20 510b57cec5SDimitry Andric 5206c3fb27SDimitry Andric // [optional.nullops], comparison with nullopt 530b57cec5SDimitry Andric template<class T> constexpr bool operator==(const optional<T>&, nullopt_t) noexcept; 5406c3fb27SDimitry Andric template<class T> constexpr bool operator==(nullopt_t, const optional<T>&) noexcept; // until C++17 5506c3fb27SDimitry Andric template<class T> constexpr bool operator!=(const optional<T>&, nullopt_t) noexcept; // until C++17 5606c3fb27SDimitry Andric template<class T> constexpr bool operator!=(nullopt_t, const optional<T>&) noexcept; // until C++17 5706c3fb27SDimitry Andric template<class T> constexpr bool operator<(const optional<T>&, nullopt_t) noexcept; // until C++17 5806c3fb27SDimitry Andric template<class T> constexpr bool operator<(nullopt_t, const optional<T>&) noexcept; // until C++17 5906c3fb27SDimitry Andric template<class T> constexpr bool operator<=(const optional<T>&, nullopt_t) noexcept; // until C++17 6006c3fb27SDimitry Andric template<class T> constexpr bool operator<=(nullopt_t, const optional<T>&) noexcept; // until C++17 6106c3fb27SDimitry Andric template<class T> constexpr bool operator>(const optional<T>&, nullopt_t) noexcept; // until C++17 6206c3fb27SDimitry Andric template<class T> constexpr bool operator>(nullopt_t, const optional<T>&) noexcept; // until C++17 6306c3fb27SDimitry Andric template<class T> constexpr bool operator>=(const optional<T>&, nullopt_t) noexcept; // until C++17 6406c3fb27SDimitry Andric template<class T> constexpr bool operator>=(nullopt_t, const optional<T>&) noexcept; // until C++17 6506c3fb27SDimitry Andric template<class T> 6606c3fb27SDimitry Andric constexpr strong_ordering operator<=>(const optional<T>&, nullopt_t) noexcept; // since C++20 670b57cec5SDimitry Andric 6806c3fb27SDimitry Andric // [optional.comp.with.t], comparison with T 690b57cec5SDimitry Andric template<class T, class U> constexpr bool operator==(const optional<T>&, const U&); 700b57cec5SDimitry Andric template<class T, class U> constexpr bool operator==(const T&, const optional<U>&); 710b57cec5SDimitry Andric template<class T, class U> constexpr bool operator!=(const optional<T>&, const U&); 720b57cec5SDimitry Andric template<class T, class U> constexpr bool operator!=(const T&, const optional<U>&); 730b57cec5SDimitry Andric template<class T, class U> constexpr bool operator<(const optional<T>&, const U&); 740b57cec5SDimitry Andric template<class T, class U> constexpr bool operator<(const T&, const optional<U>&); 750b57cec5SDimitry Andric template<class T, class U> constexpr bool operator<=(const optional<T>&, const U&); 760b57cec5SDimitry Andric template<class T, class U> constexpr bool operator<=(const T&, const optional<U>&); 770b57cec5SDimitry Andric template<class T, class U> constexpr bool operator>(const optional<T>&, const U&); 780b57cec5SDimitry Andric template<class T, class U> constexpr bool operator>(const T&, const optional<U>&); 790b57cec5SDimitry Andric template<class T, class U> constexpr bool operator>=(const optional<T>&, const U&); 800b57cec5SDimitry Andric template<class T, class U> constexpr bool operator>=(const T&, const optional<U>&); 8106c3fb27SDimitry Andric template<class T, class U> 8206c3fb27SDimitry Andric requires (!is-derived-from-optional<U>) && three_way_comparable_with<T, U> 8306c3fb27SDimitry Andric constexpr compare_three_way_result_t<T, U> 8406c3fb27SDimitry Andric operator<=>(const optional<T>&, const U&); // since C++20 850b57cec5SDimitry Andric 8606c3fb27SDimitry Andric // [optional.specalg], specialized algorithms 8706c3fb27SDimitry Andric template<class T> 8806c3fb27SDimitry Andric void swap(optional<T>&, optional<T>&) noexcept(see below ); // constexpr in C++20 8906c3fb27SDimitry Andric 9006c3fb27SDimitry Andric template<class T> 9106c3fb27SDimitry Andric constexpr optional<see below > make_optional(T&&); 920b57cec5SDimitry Andric template<class T, class... Args> 930b57cec5SDimitry Andric constexpr optional<T> make_optional(Args&&... args); 940b57cec5SDimitry Andric template<class T, class U, class... Args> 950b57cec5SDimitry Andric constexpr optional<T> make_optional(initializer_list<U> il, Args&&... args); 960b57cec5SDimitry Andric 9706c3fb27SDimitry Andric // [optional.hash], hash support 980b57cec5SDimitry Andric template<class T> struct hash; 990b57cec5SDimitry Andric template<class T> struct hash<optional<T>>; 1000b57cec5SDimitry Andric 10106c3fb27SDimitry Andric template<class T> 10206c3fb27SDimitry Andric class optional { 1030b57cec5SDimitry Andric public: 1040b57cec5SDimitry Andric using value_type = T; 1050b57cec5SDimitry Andric 10606c3fb27SDimitry Andric // [optional.ctor], constructors 1070b57cec5SDimitry Andric constexpr optional() noexcept; 1080b57cec5SDimitry Andric constexpr optional(nullopt_t) noexcept; 109bdd1243dSDimitry Andric constexpr optional(const optional &); 110bdd1243dSDimitry Andric constexpr optional(optional &&) noexcept(see below); 11106c3fb27SDimitry Andric template<class... Args> 11206c3fb27SDimitry Andric constexpr explicit optional(in_place_t, Args &&...); 1130b57cec5SDimitry Andric template<class U, class... Args> 1140b57cec5SDimitry Andric constexpr explicit optional(in_place_t, initializer_list<U>, Args &&...); 1150b57cec5SDimitry Andric template<class U = T> 11681ad6265SDimitry Andric constexpr explicit(see-below) optional(U &&); 1170b57cec5SDimitry Andric template<class U> 11881ad6265SDimitry Andric explicit(see-below) optional(const optional<U> &); // constexpr in C++20 1190b57cec5SDimitry Andric template<class U> 12081ad6265SDimitry Andric explicit(see-below) optional(optional<U> &&); // constexpr in C++20 1210b57cec5SDimitry Andric 12206c3fb27SDimitry Andric // [optional.dtor], destructor 123fe6060f1SDimitry Andric ~optional(); // constexpr in C++20 1240b57cec5SDimitry Andric 12506c3fb27SDimitry Andric // [optional.assign], assignment 126fe6060f1SDimitry Andric optional &operator=(nullopt_t) noexcept; // constexpr in C++20 127bdd1243dSDimitry Andric constexpr optional &operator=(const optional &); 128bdd1243dSDimitry Andric constexpr optional &operator=(optional &&) noexcept(see below); 129fe6060f1SDimitry Andric template<class U = T> optional &operator=(U &&); // constexpr in C++20 130fe6060f1SDimitry Andric template<class U> optional &operator=(const optional<U> &); // constexpr in C++20 131fe6060f1SDimitry Andric template<class U> optional &operator=(optional<U> &&); // constexpr in C++20 132fe6060f1SDimitry Andric template<class... Args> T& emplace(Args &&...); // constexpr in C++20 13306c3fb27SDimitry Andric template<class U, class... Args> T& emplace(initializer_list<U>, Args &&...); // constexpr in C++20 1340b57cec5SDimitry Andric 13506c3fb27SDimitry Andric // [optional.swap], swap 136fe6060f1SDimitry Andric void swap(optional &) noexcept(see below ); // constexpr in C++20 1370b57cec5SDimitry Andric 13806c3fb27SDimitry Andric // [optional.observe], observers 1390fca6ea1SDimitry Andric constexpr T const *operator->() const noexcept; 1400fca6ea1SDimitry Andric constexpr T *operator->() noexcept; 1410fca6ea1SDimitry Andric constexpr T const &operator*() const & noexcept; 1420fca6ea1SDimitry Andric constexpr T &operator*() & noexcept; 1430fca6ea1SDimitry Andric constexpr T &&operator*() && noexcept; 1440fca6ea1SDimitry Andric constexpr const T &&operator*() const && noexcept; 1450b57cec5SDimitry Andric constexpr explicit operator bool() const noexcept; 1460b57cec5SDimitry Andric constexpr bool has_value() const noexcept; 1470b57cec5SDimitry Andric constexpr T const &value() const &; 1480b57cec5SDimitry Andric constexpr T &value() &; 1490b57cec5SDimitry Andric constexpr T &&value() &&; 1500b57cec5SDimitry Andric constexpr const T &&value() const &&; 1510b57cec5SDimitry Andric template<class U> constexpr T value_or(U &&) const &; 1520b57cec5SDimitry Andric template<class U> constexpr T value_or(U &&) &&; 1530b57cec5SDimitry Andric 1540eae32dcSDimitry Andric // [optional.monadic], monadic operations 1550eae32dcSDimitry Andric template<class F> constexpr auto and_then(F&& f) &; // since C++23 1560eae32dcSDimitry Andric template<class F> constexpr auto and_then(F&& f) &&; // since C++23 1570eae32dcSDimitry Andric template<class F> constexpr auto and_then(F&& f) const&; // since C++23 1580eae32dcSDimitry Andric template<class F> constexpr auto and_then(F&& f) const&&; // since C++23 1590eae32dcSDimitry Andric template<class F> constexpr auto transform(F&& f) &; // since C++23 1600eae32dcSDimitry Andric template<class F> constexpr auto transform(F&& f) &&; // since C++23 1610eae32dcSDimitry Andric template<class F> constexpr auto transform(F&& f) const&; // since C++23 1620eae32dcSDimitry Andric template<class F> constexpr auto transform(F&& f) const&&; // since C++23 1630eae32dcSDimitry Andric template<class F> constexpr optional or_else(F&& f) &&; // since C++23 1640eae32dcSDimitry Andric template<class F> constexpr optional or_else(F&& f) const&; // since C++23 1650eae32dcSDimitry Andric 16606c3fb27SDimitry Andric // [optional.mod], modifiers 167fe6060f1SDimitry Andric void reset() noexcept; // constexpr in C++20 1680b57cec5SDimitry Andric 1690b57cec5SDimitry Andric private: 1700b57cec5SDimitry Andric T *val; // exposition only 1710b57cec5SDimitry Andric }; 1720b57cec5SDimitry Andric 1730b57cec5SDimitry Andric template<class T> 1740b57cec5SDimitry Andric optional(T) -> optional<T>; 1750b57cec5SDimitry Andric 1760b57cec5SDimitry Andric} // namespace std 1770b57cec5SDimitry Andric 1780b57cec5SDimitry Andric*/ 1790b57cec5SDimitry Andric 1800fca6ea1SDimitry Andric#include <__assert> 18106c3fb27SDimitry Andric#include <__compare/compare_three_way_result.h> 18206c3fb27SDimitry Andric#include <__compare/three_way_comparable.h> 1830eae32dcSDimitry Andric#include <__concepts/invocable.h> 184fe6060f1SDimitry Andric#include <__config> 1855f757f3fSDimitry Andric#include <__exception/exception.h> 18681ad6265SDimitry Andric#include <__functional/hash.h> 18781ad6265SDimitry Andric#include <__functional/invoke.h> 18881ad6265SDimitry Andric#include <__functional/unary_function.h> 1890fca6ea1SDimitry Andric#include <__fwd/functional.h> 19006c3fb27SDimitry Andric#include <__memory/addressof.h> 19181ad6265SDimitry Andric#include <__memory/construct_at.h> 19206c3fb27SDimitry Andric#include <__tuple/sfinae_helpers.h> 19306c3fb27SDimitry Andric#include <__type_traits/add_pointer.h> 19406c3fb27SDimitry Andric#include <__type_traits/conditional.h> 19506c3fb27SDimitry Andric#include <__type_traits/conjunction.h> 19606c3fb27SDimitry Andric#include <__type_traits/decay.h> 19706c3fb27SDimitry Andric#include <__type_traits/disjunction.h> 19806c3fb27SDimitry Andric#include <__type_traits/is_array.h> 19906c3fb27SDimitry Andric#include <__type_traits/is_assignable.h> 20006c3fb27SDimitry Andric#include <__type_traits/is_constructible.h> 20106c3fb27SDimitry Andric#include <__type_traits/is_convertible.h> 20206c3fb27SDimitry Andric#include <__type_traits/is_destructible.h> 2030fca6ea1SDimitry Andric#include <__type_traits/is_nothrow_assignable.h> 2040fca6ea1SDimitry Andric#include <__type_traits/is_nothrow_constructible.h> 20506c3fb27SDimitry Andric#include <__type_traits/is_object.h> 20606c3fb27SDimitry Andric#include <__type_traits/is_reference.h> 20706c3fb27SDimitry Andric#include <__type_traits/is_scalar.h> 20806c3fb27SDimitry Andric#include <__type_traits/is_swappable.h> 2090fca6ea1SDimitry Andric#include <__type_traits/is_trivially_assignable.h> 2100fca6ea1SDimitry Andric#include <__type_traits/is_trivially_constructible.h> 21106c3fb27SDimitry Andric#include <__type_traits/is_trivially_destructible.h> 2120fca6ea1SDimitry Andric#include <__type_traits/is_trivially_relocatable.h> 21306c3fb27SDimitry Andric#include <__type_traits/negation.h> 21406c3fb27SDimitry Andric#include <__type_traits/remove_const.h> 21506c3fb27SDimitry Andric#include <__type_traits/remove_cvref.h> 21606c3fb27SDimitry Andric#include <__type_traits/remove_reference.h> 21706c3fb27SDimitry Andric#include <__utility/declval.h> 21881ad6265SDimitry Andric#include <__utility/forward.h> 21981ad6265SDimitry Andric#include <__utility/in_place.h> 22081ad6265SDimitry Andric#include <__utility/move.h> 22181ad6265SDimitry Andric#include <__utility/swap.h> 22206c3fb27SDimitry Andric#include <__verbose_abort> 2230b57cec5SDimitry Andric#include <initializer_list> 2240b57cec5SDimitry Andric#include <new> 2250b57cec5SDimitry Andric#include <version> 2260b57cec5SDimitry Andric 22781ad6265SDimitry Andric// standard-mandated includes 228bdd1243dSDimitry Andric 229bdd1243dSDimitry Andric// [optional.syn] 23081ad6265SDimitry Andric#include <compare> 23181ad6265SDimitry Andric 2320b57cec5SDimitry Andric#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 2330b57cec5SDimitry Andric# pragma GCC system_header 2340b57cec5SDimitry Andric#endif 2350b57cec5SDimitry Andric 23606c3fb27SDimitry Andric_LIBCPP_PUSH_MACROS 23706c3fb27SDimitry Andric#include <__undef_macros> 23806c3fb27SDimitry Andric 2390b57cec5SDimitry Andricnamespace std // purposefully not using versioning namespace 2400b57cec5SDimitry Andric{ 2410b57cec5SDimitry Andric 242cb14a3feSDimitry Andricclass _LIBCPP_EXPORTED_FROM_ABI _LIBCPP_AVAILABILITY_BAD_OPTIONAL_ACCESS bad_optional_access : public exception { 2430b57cec5SDimitry Andricpublic: 2445f757f3fSDimitry Andric _LIBCPP_HIDE_FROM_ABI bad_optional_access() _NOEXCEPT = default; 2455f757f3fSDimitry Andric _LIBCPP_HIDE_FROM_ABI bad_optional_access(const bad_optional_access&) _NOEXCEPT = default; 2465f757f3fSDimitry Andric _LIBCPP_HIDE_FROM_ABI bad_optional_access& operator=(const bad_optional_access&) _NOEXCEPT = default; 2470b57cec5SDimitry Andric // Get the key function ~bad_optional_access() into the dylib 248bdd1243dSDimitry Andric ~bad_optional_access() _NOEXCEPT override; 249bdd1243dSDimitry Andric const char* what() const _NOEXCEPT override; 2500b57cec5SDimitry Andric}; 2510b57cec5SDimitry Andric 2520eae32dcSDimitry Andric} // namespace std 2530b57cec5SDimitry Andric 25406c3fb27SDimitry Andric#if _LIBCPP_STD_VER >= 17 2550b57cec5SDimitry Andric 2560b57cec5SDimitry Andric_LIBCPP_BEGIN_NAMESPACE_STD 2570b57cec5SDimitry Andric 258cb14a3feSDimitry Andric_LIBCPP_NORETURN inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS void 259cb14a3feSDimitry Andric__throw_bad_optional_access() { 26006c3fb27SDimitry Andric# ifndef _LIBCPP_HAS_NO_EXCEPTIONS 2610b57cec5SDimitry Andric throw bad_optional_access(); 2620b57cec5SDimitry Andric# else 26306c3fb27SDimitry Andric _LIBCPP_VERBOSE_ABORT("bad_optional_access was thrown in -fno-exceptions mode"); 2640b57cec5SDimitry Andric# endif 2650b57cec5SDimitry Andric} 2660b57cec5SDimitry Andric 267cb14a3feSDimitry Andricstruct nullopt_t { 268cb14a3feSDimitry Andric struct __secret_tag { 269cb14a3feSDimitry Andric explicit __secret_tag() = default; 270cb14a3feSDimitry Andric }; 2715f757f3fSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr explicit nullopt_t(__secret_tag, __secret_tag) noexcept {} 2720b57cec5SDimitry Andric}; 2730b57cec5SDimitry Andric 274349cc55cSDimitry Andricinline constexpr nullopt_t nullopt{nullopt_t::__secret_tag{}, nullopt_t::__secret_tag{}}; 2750b57cec5SDimitry Andric 2760eae32dcSDimitry Andricstruct __optional_construct_from_invoke_tag {}; 2770eae32dcSDimitry Andric 2780b57cec5SDimitry Andrictemplate <class _Tp, bool = is_trivially_destructible<_Tp>::value> 2790b57cec5SDimitry Andricstruct __optional_destruct_base; 2800b57cec5SDimitry Andric 2810b57cec5SDimitry Andrictemplate <class _Tp> 282cb14a3feSDimitry Andricstruct __optional_destruct_base<_Tp, false> { 2830b57cec5SDimitry Andric typedef _Tp value_type; 284cb14a3feSDimitry Andric static_assert(is_object_v<value_type>, "instantiation of optional with a non-object type is undefined behavior"); 285cb14a3feSDimitry Andric union { 2860b57cec5SDimitry Andric char __null_state_; 2870b57cec5SDimitry Andric value_type __val_; 2880b57cec5SDimitry Andric }; 2890b57cec5SDimitry Andric bool __engaged_; 2900b57cec5SDimitry Andric 291cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 ~__optional_destruct_base() { 2920b57cec5SDimitry Andric if (__engaged_) 2930b57cec5SDimitry Andric __val_.~value_type(); 2940b57cec5SDimitry Andric } 2950b57cec5SDimitry Andric 296cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr __optional_destruct_base() noexcept : __null_state_(), __engaged_(false) {} 2970b57cec5SDimitry Andric 2980b57cec5SDimitry Andric template <class... _Args> 299cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr explicit __optional_destruct_base(in_place_t, _Args&&... __args) 300cb14a3feSDimitry Andric : __val_(std::forward<_Args>(__args)...), __engaged_(true) {} 3010b57cec5SDimitry Andric 30206c3fb27SDimitry Andric# if _LIBCPP_STD_VER >= 23 3030eae32dcSDimitry Andric template <class _Fp, class... _Args> 304*62987288SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr explicit __optional_destruct_base( 305cb14a3feSDimitry Andric __optional_construct_from_invoke_tag, _Fp&& __f, _Args&&... __args) 3065f757f3fSDimitry Andric : __val_(std::invoke(std::forward<_Fp>(__f), std::forward<_Args>(__args)...)), __engaged_(true) {} 3070eae32dcSDimitry Andric# endif 3080eae32dcSDimitry Andric 309cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void reset() noexcept { 310cb14a3feSDimitry Andric if (__engaged_) { 3110b57cec5SDimitry Andric __val_.~value_type(); 3120b57cec5SDimitry Andric __engaged_ = false; 3130b57cec5SDimitry Andric } 3140b57cec5SDimitry Andric } 3150b57cec5SDimitry Andric}; 3160b57cec5SDimitry Andric 3170b57cec5SDimitry Andrictemplate <class _Tp> 318cb14a3feSDimitry Andricstruct __optional_destruct_base<_Tp, true> { 3190b57cec5SDimitry Andric typedef _Tp value_type; 320cb14a3feSDimitry Andric static_assert(is_object_v<value_type>, "instantiation of optional with a non-object type is undefined behavior"); 321cb14a3feSDimitry Andric union { 3220b57cec5SDimitry Andric char __null_state_; 3230b57cec5SDimitry Andric value_type __val_; 3240b57cec5SDimitry Andric }; 3250b57cec5SDimitry Andric bool __engaged_; 3260b57cec5SDimitry Andric 327cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr __optional_destruct_base() noexcept : __null_state_(), __engaged_(false) {} 3280b57cec5SDimitry Andric 3290b57cec5SDimitry Andric template <class... _Args> 330cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr explicit __optional_destruct_base(in_place_t, _Args&&... __args) 331cb14a3feSDimitry Andric : __val_(std::forward<_Args>(__args)...), __engaged_(true) {} 3320b57cec5SDimitry Andric 33306c3fb27SDimitry Andric# if _LIBCPP_STD_VER >= 23 3340eae32dcSDimitry Andric template <class _Fp, class... _Args> 335cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr __optional_destruct_base( 336cb14a3feSDimitry Andric __optional_construct_from_invoke_tag, _Fp&& __f, _Args&&... __args) 3375f757f3fSDimitry Andric : __val_(std::invoke(std::forward<_Fp>(__f), std::forward<_Args>(__args)...)), __engaged_(true) {} 3380eae32dcSDimitry Andric# endif 3390eae32dcSDimitry Andric 340cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void reset() noexcept { 341cb14a3feSDimitry Andric if (__engaged_) { 3420b57cec5SDimitry Andric __engaged_ = false; 3430b57cec5SDimitry Andric } 3440b57cec5SDimitry Andric } 3450b57cec5SDimitry Andric}; 3460b57cec5SDimitry Andric 3470b57cec5SDimitry Andrictemplate <class _Tp, bool = is_reference<_Tp>::value> 348cb14a3feSDimitry Andricstruct __optional_storage_base : __optional_destruct_base<_Tp> { 3490b57cec5SDimitry Andric using __base = __optional_destruct_base<_Tp>; 3500b57cec5SDimitry Andric using value_type = _Tp; 3510b57cec5SDimitry Andric using __base::__base; 3520b57cec5SDimitry Andric 353cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr bool has_value() const noexcept { return this->__engaged_; } 3540b57cec5SDimitry Andric 355cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr value_type& __get() & noexcept { return this->__val_; } 356cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr const value_type& __get() const& noexcept { return this->__val_; } 357cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr value_type&& __get() && noexcept { return std::move(this->__val_); } 358cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr const value_type&& __get() const&& noexcept { return std::move(this->__val_); } 3590b57cec5SDimitry Andric 3600b57cec5SDimitry Andric template <class... _Args> 361cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __construct(_Args&&... __args) { 36206c3fb27SDimitry Andric _LIBCPP_ASSERT_INTERNAL(!has_value(), "__construct called for engaged __optional_storage"); 3635f757f3fSDimitry Andric std::__construct_at(std::addressof(this->__val_), std::forward<_Args>(__args)...); 3640b57cec5SDimitry Andric this->__engaged_ = true; 3650b57cec5SDimitry Andric } 3660b57cec5SDimitry Andric 3670b57cec5SDimitry Andric template <class _That> 368cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __construct_from(_That&& __opt) { 3690b57cec5SDimitry Andric if (__opt.has_value()) 3705f757f3fSDimitry Andric __construct(std::forward<_That>(__opt).__get()); 3710b57cec5SDimitry Andric } 3720b57cec5SDimitry Andric 3730b57cec5SDimitry Andric template <class _That> 374cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __assign_from(_That&& __opt) { 375cb14a3feSDimitry Andric if (this->__engaged_ == __opt.has_value()) { 3760b57cec5SDimitry Andric if (this->__engaged_) 3775f757f3fSDimitry Andric this->__val_ = std::forward<_That>(__opt).__get(); 378cb14a3feSDimitry Andric } else { 3790b57cec5SDimitry Andric if (this->__engaged_) 3800b57cec5SDimitry Andric this->reset(); 3810b57cec5SDimitry Andric else 3825f757f3fSDimitry Andric __construct(std::forward<_That>(__opt).__get()); 3830b57cec5SDimitry Andric } 3840b57cec5SDimitry Andric } 3850b57cec5SDimitry Andric}; 3860b57cec5SDimitry Andric 38781ad6265SDimitry Andric// optional<T&> is currently required to be ill-formed. However, it may 38881ad6265SDimitry Andric// be allowed in the future. For this reason, it has already been implemented 38981ad6265SDimitry Andric// to ensure we can make the change in an ABI-compatible manner. 3900b57cec5SDimitry Andrictemplate <class _Tp> 391cb14a3feSDimitry Andricstruct __optional_storage_base<_Tp, true> { 3920b57cec5SDimitry Andric using value_type = _Tp; 3930b57cec5SDimitry Andric using __raw_type = remove_reference_t<_Tp>; 3940b57cec5SDimitry Andric __raw_type* __value_; 3950b57cec5SDimitry Andric 3960b57cec5SDimitry Andric template <class _Up> 39706c3fb27SDimitry Andric static _LIBCPP_HIDE_FROM_ABI constexpr bool __can_bind_reference() { 398bdd1243dSDimitry Andric using _RawUp = __libcpp_remove_reference_t<_Up>; 3990b57cec5SDimitry Andric using _UpPtr = _RawUp*; 400bdd1243dSDimitry Andric using _RawTp = __libcpp_remove_reference_t<_Tp>; 4010b57cec5SDimitry Andric using _TpPtr = _RawTp*; 402cb14a3feSDimitry Andric using _CheckLValueArg = 403cb14a3feSDimitry Andric integral_constant<bool, 404cb14a3feSDimitry Andric (is_lvalue_reference<_Up>::value && is_convertible<_UpPtr, _TpPtr>::value) || 405cb14a3feSDimitry Andric is_same<_RawUp, reference_wrapper<_RawTp>>::value || 406cb14a3feSDimitry Andric is_same<_RawUp, reference_wrapper<__remove_const_t<_RawTp>>>::value >; 407cb14a3feSDimitry Andric return (is_lvalue_reference<_Tp>::value && _CheckLValueArg::value) || 408cb14a3feSDimitry Andric (is_rvalue_reference<_Tp>::value && !is_lvalue_reference<_Up>::value && 4090b57cec5SDimitry Andric is_convertible<_UpPtr, _TpPtr>::value); 4100b57cec5SDimitry Andric } 4110b57cec5SDimitry Andric 412cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr __optional_storage_base() noexcept : __value_(nullptr) {} 4130b57cec5SDimitry Andric 4140b57cec5SDimitry Andric template <class _UArg> 415cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr explicit __optional_storage_base(in_place_t, _UArg&& __uarg) 416cb14a3feSDimitry Andric : __value_(std::addressof(__uarg)) { 4170b57cec5SDimitry Andric static_assert(__can_bind_reference<_UArg>(), 4180b57cec5SDimitry Andric "Attempted to construct a reference element in tuple from a " 4190b57cec5SDimitry Andric "possible temporary"); 4200b57cec5SDimitry Andric } 4210b57cec5SDimitry Andric 422cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void reset() noexcept { __value_ = nullptr; } 4230b57cec5SDimitry Andric 424cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr bool has_value() const noexcept { return __value_ != nullptr; } 4250b57cec5SDimitry Andric 426cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr value_type& __get() const& noexcept { return *__value_; } 4270b57cec5SDimitry Andric 428cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr value_type&& __get() const&& noexcept { return std::forward<value_type>(*__value_); } 4290b57cec5SDimitry Andric 4300b57cec5SDimitry Andric template <class _UArg> 431cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __construct(_UArg&& __val) { 43206c3fb27SDimitry Andric _LIBCPP_ASSERT_INTERNAL(!has_value(), "__construct called for engaged __optional_storage"); 4330b57cec5SDimitry Andric static_assert(__can_bind_reference<_UArg>(), 4340b57cec5SDimitry Andric "Attempted to construct a reference element in tuple from a " 4350b57cec5SDimitry Andric "possible temporary"); 4365f757f3fSDimitry Andric __value_ = std::addressof(__val); 4370b57cec5SDimitry Andric } 4380b57cec5SDimitry Andric 4390b57cec5SDimitry Andric template <class _That> 440cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __construct_from(_That&& __opt) { 4410b57cec5SDimitry Andric if (__opt.has_value()) 4425f757f3fSDimitry Andric __construct(std::forward<_That>(__opt).__get()); 4430b57cec5SDimitry Andric } 4440b57cec5SDimitry Andric 4450b57cec5SDimitry Andric template <class _That> 446cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __assign_from(_That&& __opt) { 447cb14a3feSDimitry Andric if (has_value() == __opt.has_value()) { 4480b57cec5SDimitry Andric if (has_value()) 4495f757f3fSDimitry Andric *__value_ = std::forward<_That>(__opt).__get(); 450cb14a3feSDimitry Andric } else { 4510b57cec5SDimitry Andric if (has_value()) 4520b57cec5SDimitry Andric reset(); 4530b57cec5SDimitry Andric else 4545f757f3fSDimitry Andric __construct(std::forward<_That>(__opt).__get()); 4550b57cec5SDimitry Andric } 4560b57cec5SDimitry Andric } 4570b57cec5SDimitry Andric}; 4580b57cec5SDimitry Andric 4590b57cec5SDimitry Andrictemplate <class _Tp, bool = is_trivially_copy_constructible<_Tp>::value> 460cb14a3feSDimitry Andricstruct __optional_copy_base : __optional_storage_base<_Tp> { 4610b57cec5SDimitry Andric using __optional_storage_base<_Tp>::__optional_storage_base; 4620b57cec5SDimitry Andric}; 4630b57cec5SDimitry Andric 4640b57cec5SDimitry Andrictemplate <class _Tp> 465cb14a3feSDimitry Andricstruct __optional_copy_base<_Tp, false> : __optional_storage_base<_Tp> { 4660b57cec5SDimitry Andric using __optional_storage_base<_Tp>::__optional_storage_base; 4670b57cec5SDimitry Andric 468cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI __optional_copy_base() = default; 4690b57cec5SDimitry Andric 470cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 __optional_copy_base(const __optional_copy_base& __opt) { 4710b57cec5SDimitry Andric this->__construct_from(__opt); 4720b57cec5SDimitry Andric } 4730b57cec5SDimitry Andric 474cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI __optional_copy_base(__optional_copy_base&&) = default; 475cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI __optional_copy_base& operator=(const __optional_copy_base&) = default; 476cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI __optional_copy_base& operator=(__optional_copy_base&&) = default; 4770b57cec5SDimitry Andric}; 4780b57cec5SDimitry Andric 4790b57cec5SDimitry Andrictemplate <class _Tp, bool = is_trivially_move_constructible<_Tp>::value> 480cb14a3feSDimitry Andricstruct __optional_move_base : __optional_copy_base<_Tp> { 4810b57cec5SDimitry Andric using __optional_copy_base<_Tp>::__optional_copy_base; 4820b57cec5SDimitry Andric}; 4830b57cec5SDimitry Andric 4840b57cec5SDimitry Andrictemplate <class _Tp> 485cb14a3feSDimitry Andricstruct __optional_move_base<_Tp, false> : __optional_copy_base<_Tp> { 4860b57cec5SDimitry Andric using value_type = _Tp; 4870b57cec5SDimitry Andric using __optional_copy_base<_Tp>::__optional_copy_base; 4880b57cec5SDimitry Andric 489cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI __optional_move_base() = default; 490cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI __optional_move_base(const __optional_move_base&) = default; 4910b57cec5SDimitry Andric 492cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 493cb14a3feSDimitry Andric __optional_move_base(__optional_move_base&& __opt) noexcept(is_nothrow_move_constructible_v<value_type>) { 4945f757f3fSDimitry Andric this->__construct_from(std::move(__opt)); 4950b57cec5SDimitry Andric } 4960b57cec5SDimitry Andric 497cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI __optional_move_base& operator=(const __optional_move_base&) = default; 498cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI __optional_move_base& operator=(__optional_move_base&&) = default; 4990b57cec5SDimitry Andric}; 5000b57cec5SDimitry Andric 501cb14a3feSDimitry Andrictemplate <class _Tp, 502cb14a3feSDimitry Andric bool = is_trivially_destructible<_Tp>::value && is_trivially_copy_constructible<_Tp>::value && 5030b57cec5SDimitry Andric is_trivially_copy_assignable<_Tp>::value> 504cb14a3feSDimitry Andricstruct __optional_copy_assign_base : __optional_move_base<_Tp> { 5050b57cec5SDimitry Andric using __optional_move_base<_Tp>::__optional_move_base; 5060b57cec5SDimitry Andric}; 5070b57cec5SDimitry Andric 5080b57cec5SDimitry Andrictemplate <class _Tp> 509cb14a3feSDimitry Andricstruct __optional_copy_assign_base<_Tp, false> : __optional_move_base<_Tp> { 5100b57cec5SDimitry Andric using __optional_move_base<_Tp>::__optional_move_base; 5110b57cec5SDimitry Andric 512cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI __optional_copy_assign_base() = default; 513cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI __optional_copy_assign_base(const __optional_copy_assign_base&) = default; 514cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI __optional_copy_assign_base(__optional_copy_assign_base&&) = default; 5150b57cec5SDimitry Andric 516cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 __optional_copy_assign_base& 517cb14a3feSDimitry Andric operator=(const __optional_copy_assign_base& __opt) { 5180b57cec5SDimitry Andric this->__assign_from(__opt); 5190b57cec5SDimitry Andric return *this; 5200b57cec5SDimitry Andric } 5210b57cec5SDimitry Andric 522cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI __optional_copy_assign_base& operator=(__optional_copy_assign_base&&) = default; 5230b57cec5SDimitry Andric}; 5240b57cec5SDimitry Andric 525cb14a3feSDimitry Andrictemplate <class _Tp, 526cb14a3feSDimitry Andric bool = is_trivially_destructible<_Tp>::value && is_trivially_move_constructible<_Tp>::value && 5270b57cec5SDimitry Andric is_trivially_move_assignable<_Tp>::value> 528cb14a3feSDimitry Andricstruct __optional_move_assign_base : __optional_copy_assign_base<_Tp> { 5290b57cec5SDimitry Andric using __optional_copy_assign_base<_Tp>::__optional_copy_assign_base; 5300b57cec5SDimitry Andric}; 5310b57cec5SDimitry Andric 5320b57cec5SDimitry Andrictemplate <class _Tp> 533cb14a3feSDimitry Andricstruct __optional_move_assign_base<_Tp, false> : __optional_copy_assign_base<_Tp> { 5340b57cec5SDimitry Andric using value_type = _Tp; 5350b57cec5SDimitry Andric using __optional_copy_assign_base<_Tp>::__optional_copy_assign_base; 5360b57cec5SDimitry Andric 537cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI __optional_move_assign_base() = default; 538cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI __optional_move_assign_base(const __optional_move_assign_base& __opt) = default; 539cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI __optional_move_assign_base(__optional_move_assign_base&&) = default; 540cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI __optional_move_assign_base& operator=(const __optional_move_assign_base&) = default; 5410b57cec5SDimitry Andric 542cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 __optional_move_assign_base& 543cb14a3feSDimitry Andric operator=(__optional_move_assign_base&& __opt) noexcept( 544cb14a3feSDimitry Andric is_nothrow_move_assignable_v<value_type> && is_nothrow_move_constructible_v<value_type>) { 5455f757f3fSDimitry Andric this->__assign_from(std::move(__opt)); 5460b57cec5SDimitry Andric return *this; 5470b57cec5SDimitry Andric } 5480b57cec5SDimitry Andric}; 5490b57cec5SDimitry Andric 5500b57cec5SDimitry Andrictemplate <class _Tp> 551cb14a3feSDimitry Andricusing __optional_sfinae_ctor_base_t = 552cb14a3feSDimitry Andric __sfinae_ctor_base< is_copy_constructible<_Tp>::value, is_move_constructible<_Tp>::value >; 5530b57cec5SDimitry Andric 5540b57cec5SDimitry Andrictemplate <class _Tp> 555cb14a3feSDimitry Andricusing __optional_sfinae_assign_base_t = 556cb14a3feSDimitry Andric __sfinae_assign_base< (is_copy_constructible<_Tp>::value && is_copy_assignable<_Tp>::value), 557cb14a3feSDimitry Andric (is_move_constructible<_Tp>::value && is_move_assignable<_Tp>::value) >; 5580b57cec5SDimitry Andric 5590b57cec5SDimitry Andrictemplate <class _Tp> 5600eae32dcSDimitry Andricclass optional; 56106c3fb27SDimitry Andric 56206c3fb27SDimitry Andric# if _LIBCPP_STD_VER >= 20 56306c3fb27SDimitry Andric 56406c3fb27SDimitry Andrictemplate <class _Tp> 56506c3fb27SDimitry Andricconcept __is_derived_from_optional = requires(const _Tp& __t) { []<class _Up>(const optional<_Up>&) {}(__t); }; 56606c3fb27SDimitry Andric 56706c3fb27SDimitry Andric# endif // _LIBCPP_STD_VER >= 20 56806c3fb27SDimitry Andric 5690eae32dcSDimitry Andrictemplate <class _Tp> 5700eae32dcSDimitry Andricstruct __is_std_optional : false_type {}; 571cb14a3feSDimitry Andrictemplate <class _Tp> 572cb14a3feSDimitry Andricstruct __is_std_optional<optional<_Tp>> : true_type {}; 5730eae32dcSDimitry Andric 5740eae32dcSDimitry Andrictemplate <class _Tp> 57506c3fb27SDimitry Andricclass _LIBCPP_DECLSPEC_EMPTY_BASES optional 576cb14a3feSDimitry Andric : private __optional_move_assign_base<_Tp>, 577cb14a3feSDimitry Andric private __optional_sfinae_ctor_base_t<_Tp>, 578cb14a3feSDimitry Andric private __optional_sfinae_assign_base_t<_Tp> { 5790b57cec5SDimitry Andric using __base = __optional_move_assign_base<_Tp>; 580cb14a3feSDimitry Andric 5810b57cec5SDimitry Andricpublic: 5820b57cec5SDimitry Andric using value_type = _Tp; 5830b57cec5SDimitry Andric 5840fca6ea1SDimitry Andric using __trivially_relocatable = conditional_t<__libcpp_is_trivially_relocatable<_Tp>::value, optional, void>; 5850fca6ea1SDimitry Andric 5860b57cec5SDimitry Andricprivate: 5870b57cec5SDimitry Andric // Disable the reference extension using this static assert. 588bdd1243dSDimitry Andric static_assert(!is_same_v<__remove_cvref_t<value_type>, in_place_t>, 5890b57cec5SDimitry Andric "instantiation of optional with in_place_t is ill-formed"); 590bdd1243dSDimitry Andric static_assert(!is_same_v<__remove_cvref_t<value_type>, nullopt_t>, 5910b57cec5SDimitry Andric "instantiation of optional with nullopt_t is ill-formed"); 592cb14a3feSDimitry Andric static_assert(!is_reference_v<value_type>, "instantiation of optional with a reference type is ill-formed"); 593cb14a3feSDimitry Andric static_assert(is_destructible_v<value_type>, "instantiation of optional with a non-destructible type is ill-formed"); 594cb14a3feSDimitry Andric static_assert(!is_array_v<value_type>, "instantiation of optional with an array type is ill-formed"); 5950b57cec5SDimitry Andric 5960b57cec5SDimitry Andric // LWG2756: conditionally explicit conversion from _Up 5970b57cec5SDimitry Andric struct _CheckOptionalArgsConstructor { 5980b57cec5SDimitry Andric template <class _Up> 59906c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI static constexpr bool __enable_implicit() { 600cb14a3feSDimitry Andric return is_constructible_v<_Tp, _Up&&> && is_convertible_v<_Up&&, _Tp>; 6010b57cec5SDimitry Andric } 6020b57cec5SDimitry Andric 6030b57cec5SDimitry Andric template <class _Up> 60406c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI static constexpr bool __enable_explicit() { 605cb14a3feSDimitry Andric return is_constructible_v<_Tp, _Up&&> && !is_convertible_v<_Up&&, _Tp>; 6060b57cec5SDimitry Andric } 6070b57cec5SDimitry Andric }; 6080b57cec5SDimitry Andric template <class _Up> 609cb14a3feSDimitry Andric using _CheckOptionalArgsCtor = 610cb14a3feSDimitry Andric _If< _IsNotSame<__remove_cvref_t<_Up>, in_place_t>::value && _IsNotSame<__remove_cvref_t<_Up>, optional>::value && 6115f757f3fSDimitry Andric (!is_same_v<remove_cv_t<_Tp>, bool> || !__is_std_optional<__remove_cvref_t<_Up>>::value), 6120b57cec5SDimitry Andric _CheckOptionalArgsConstructor, 613cb14a3feSDimitry Andric __check_tuple_constructor_fail >; 6140b57cec5SDimitry Andric template <class _QualUp> 6150b57cec5SDimitry Andric struct _CheckOptionalLikeConstructor { 6160b57cec5SDimitry Andric template <class _Up, class _Opt = optional<_Up>> 617cb14a3feSDimitry Andric using __check_constructible_from_opt = 618cb14a3feSDimitry Andric _Or< is_constructible<_Tp, _Opt&>, 6190b57cec5SDimitry Andric is_constructible<_Tp, _Opt const&>, 6200b57cec5SDimitry Andric is_constructible<_Tp, _Opt&&>, 6210b57cec5SDimitry Andric is_constructible<_Tp, _Opt const&&>, 6220b57cec5SDimitry Andric is_convertible<_Opt&, _Tp>, 6230b57cec5SDimitry Andric is_convertible<_Opt const&, _Tp>, 6240b57cec5SDimitry Andric is_convertible<_Opt&&, _Tp>, 625cb14a3feSDimitry Andric is_convertible<_Opt const&&, _Tp> >; 6260b57cec5SDimitry Andric template <class _Up, class _Opt = optional<_Up>> 627cb14a3feSDimitry Andric using __check_assignable_from_opt = 628cb14a3feSDimitry Andric _Or< is_assignable<_Tp&, _Opt&>, 6290b57cec5SDimitry Andric is_assignable<_Tp&, _Opt const&>, 6300b57cec5SDimitry Andric is_assignable<_Tp&, _Opt&&>, 631cb14a3feSDimitry Andric is_assignable<_Tp&, _Opt const&&> >; 6320b57cec5SDimitry Andric template <class _Up, class _QUp = _QualUp> 63306c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI static constexpr bool __enable_implicit() { 6340b57cec5SDimitry Andric return is_convertible<_QUp, _Tp>::value && 6355f757f3fSDimitry Andric (is_same_v<remove_cv_t<_Tp>, bool> || !__check_constructible_from_opt<_Up>::value); 6360b57cec5SDimitry Andric } 6370b57cec5SDimitry Andric template <class _Up, class _QUp = _QualUp> 63806c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI static constexpr bool __enable_explicit() { 6390b57cec5SDimitry Andric return !is_convertible<_QUp, _Tp>::value && 6405f757f3fSDimitry Andric (is_same_v<remove_cv_t<_Tp>, bool> || !__check_constructible_from_opt<_Up>::value); 6410b57cec5SDimitry Andric } 6420b57cec5SDimitry Andric template <class _Up, class _QUp = _QualUp> 64306c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI static constexpr bool __enable_assign() { 644e8d8bef9SDimitry Andric // Construction and assignability of _QUp to _Tp has already been 6450b57cec5SDimitry Andric // checked. 646cb14a3feSDimitry Andric return !__check_constructible_from_opt<_Up>::value && !__check_assignable_from_opt<_Up>::value; 6470b57cec5SDimitry Andric } 6480b57cec5SDimitry Andric }; 6490b57cec5SDimitry Andric 6500b57cec5SDimitry Andric template <class _Up, class _QualUp> 651cb14a3feSDimitry Andric using _CheckOptionalLikeCtor = 652cb14a3feSDimitry Andric _If< _And< _IsNotSame<_Up, _Tp>, is_constructible<_Tp, _QualUp> >::value, 6530b57cec5SDimitry Andric _CheckOptionalLikeConstructor<_QualUp>, 654cb14a3feSDimitry Andric __check_tuple_constructor_fail >; 6550b57cec5SDimitry Andric template <class _Up, class _QualUp> 656cb14a3feSDimitry Andric using _CheckOptionalLikeAssign = 657cb14a3feSDimitry Andric _If< _And< _IsNotSame<_Up, _Tp>, is_constructible<_Tp, _QualUp>, is_assignable<_Tp&, _QualUp> >::value, 6580b57cec5SDimitry Andric _CheckOptionalLikeConstructor<_QualUp>, 659cb14a3feSDimitry Andric __check_tuple_constructor_fail >; 6600eae32dcSDimitry Andric 6610b57cec5SDimitry Andricpublic: 6625f757f3fSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr optional() noexcept {} 6635f757f3fSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr optional(const optional&) = default; 6645f757f3fSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr optional(optional&&) = default; 6655f757f3fSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr optional(nullopt_t) noexcept {} 6660b57cec5SDimitry Andric 667cb14a3feSDimitry Andric template < 668cb14a3feSDimitry Andric class _InPlaceT, 669cb14a3feSDimitry Andric class... _Args, 670cb14a3feSDimitry Andric class = enable_if_t< _And< _IsSame<_InPlaceT, in_place_t>, is_constructible<value_type, _Args...> >::value > > 671cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr explicit optional(_InPlaceT, _Args&&... __args) 6725f757f3fSDimitry Andric : __base(in_place, std::forward<_Args>(__args)...) {} 6730b57cec5SDimitry Andric 674cb14a3feSDimitry Andric template <class _Up, 675cb14a3feSDimitry Andric class... _Args, 676cb14a3feSDimitry Andric class = enable_if_t< is_constructible_v<value_type, initializer_list<_Up>&, _Args...>> > 677cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr explicit optional(in_place_t, initializer_list<_Up> __il, _Args&&... __args) 6785f757f3fSDimitry Andric : __base(in_place, __il, std::forward<_Args>(__args)...) {} 6790b57cec5SDimitry Andric 680cb14a3feSDimitry Andric template <class _Up = value_type, 681cb14a3feSDimitry Andric enable_if_t< _CheckOptionalArgsCtor<_Up>::template __enable_implicit<_Up>(), int> = 0> 682cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr optional(_Up&& __v) : __base(in_place, std::forward<_Up>(__v)) {} 6830b57cec5SDimitry Andric 684cb14a3feSDimitry Andric template <class _Up, enable_if_t< _CheckOptionalArgsCtor<_Up>::template __enable_explicit<_Up>(), int> = 0> 685cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr explicit optional(_Up&& __v) : __base(in_place, std::forward<_Up>(__v)) {} 6860b57cec5SDimitry Andric 6870b57cec5SDimitry Andric // LWG2756: conditionally explicit conversion from const optional<_Up>& 688cb14a3feSDimitry Andric template <class _Up, 689cb14a3feSDimitry Andric enable_if_t< _CheckOptionalLikeCtor<_Up, _Up const&>::template __enable_implicit<_Up>(), int> = 0> 690cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 optional(const optional<_Up>& __v) { 6910b57cec5SDimitry Andric this->__construct_from(__v); 6920b57cec5SDimitry Andric } 693cb14a3feSDimitry Andric template <class _Up, 694cb14a3feSDimitry Andric enable_if_t< _CheckOptionalLikeCtor<_Up, _Up const&>::template __enable_explicit<_Up>(), int> = 0> 695cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 explicit optional(const optional<_Up>& __v) { 6960b57cec5SDimitry Andric this->__construct_from(__v); 6970b57cec5SDimitry Andric } 6980b57cec5SDimitry Andric 6990b57cec5SDimitry Andric // LWG2756: conditionally explicit conversion from optional<_Up>&& 700cb14a3feSDimitry Andric template <class _Up, enable_if_t< _CheckOptionalLikeCtor<_Up, _Up&&>::template __enable_implicit<_Up>(), int> = 0> 701cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 optional(optional<_Up>&& __v) { 7025f757f3fSDimitry Andric this->__construct_from(std::move(__v)); 7030b57cec5SDimitry Andric } 704cb14a3feSDimitry Andric template <class _Up, enable_if_t< _CheckOptionalLikeCtor<_Up, _Up&&>::template __enable_explicit<_Up>(), int> = 0> 705cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 explicit optional(optional<_Up>&& __v) { 7065f757f3fSDimitry Andric this->__construct_from(std::move(__v)); 7070b57cec5SDimitry Andric } 7080b57cec5SDimitry Andric 70906c3fb27SDimitry Andric# if _LIBCPP_STD_VER >= 23 710*62987288SDimitry Andric template <class _Tag, 711*62987288SDimitry Andric class _Fp, 712*62987288SDimitry Andric class... _Args, 713*62987288SDimitry Andric __enable_if_t<_IsSame<_Tag, __optional_construct_from_invoke_tag>::value, int> = 0> 714*62987288SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr explicit optional(_Tag, _Fp&& __f, _Args&&... __args) 715cb14a3feSDimitry Andric : __base(__optional_construct_from_invoke_tag{}, std::forward<_Fp>(__f), std::forward<_Args>(__args)...) {} 7160eae32dcSDimitry Andric# endif 7170eae32dcSDimitry Andric 718cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 optional& operator=(nullopt_t) noexcept { 7190b57cec5SDimitry Andric reset(); 7200b57cec5SDimitry Andric return *this; 7210b57cec5SDimitry Andric } 7220b57cec5SDimitry Andric 72306c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr optional& operator=(const optional&) = default; 72406c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr optional& operator=(optional&&) = default; 7250b57cec5SDimitry Andric 7260b57cec5SDimitry Andric // LWG2756 727cb14a3feSDimitry Andric template < 728cb14a3feSDimitry Andric class _Up = value_type, 729cb14a3feSDimitry Andric class = enable_if_t< _And< _IsNotSame<__remove_cvref_t<_Up>, optional>, 730cb14a3feSDimitry Andric _Or< _IsNotSame<__remove_cvref_t<_Up>, value_type>, _Not<is_scalar<value_type>> >, 7310b57cec5SDimitry Andric is_constructible<value_type, _Up>, 732cb14a3feSDimitry Andric is_assignable<value_type&, _Up> >::value> > 733cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 optional& operator=(_Up&& __v) { 7340b57cec5SDimitry Andric if (this->has_value()) 7355f757f3fSDimitry Andric this->__get() = std::forward<_Up>(__v); 7360b57cec5SDimitry Andric else 7375f757f3fSDimitry Andric this->__construct(std::forward<_Up>(__v)); 7380b57cec5SDimitry Andric return *this; 7390b57cec5SDimitry Andric } 7400b57cec5SDimitry Andric 7410b57cec5SDimitry Andric // LWG2756 742cb14a3feSDimitry Andric template <class _Up, 743cb14a3feSDimitry Andric enable_if_t< _CheckOptionalLikeAssign<_Up, _Up const&>::template __enable_assign<_Up>(), int> = 0> 744cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 optional& operator=(const optional<_Up>& __v) { 7450b57cec5SDimitry Andric this->__assign_from(__v); 7460b57cec5SDimitry Andric return *this; 7470b57cec5SDimitry Andric } 7480b57cec5SDimitry Andric 7490b57cec5SDimitry Andric // LWG2756 750cb14a3feSDimitry Andric template <class _Up, enable_if_t< _CheckOptionalLikeCtor<_Up, _Up&&>::template __enable_assign<_Up>(), int> = 0> 751cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 optional& operator=(optional<_Up>&& __v) { 7525f757f3fSDimitry Andric this->__assign_from(std::move(__v)); 7530b57cec5SDimitry Andric return *this; 7540b57cec5SDimitry Andric } 7550b57cec5SDimitry Andric 756cb14a3feSDimitry Andric template <class... _Args, class = enable_if_t< is_constructible_v<value_type, _Args...> > > 757cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _Tp& emplace(_Args&&... __args) { 7580b57cec5SDimitry Andric reset(); 7595f757f3fSDimitry Andric this->__construct(std::forward<_Args>(__args)...); 7600b57cec5SDimitry Andric return this->__get(); 7610b57cec5SDimitry Andric } 7620b57cec5SDimitry Andric 763cb14a3feSDimitry Andric template <class _Up, 764cb14a3feSDimitry Andric class... _Args, 765cb14a3feSDimitry Andric class = enable_if_t< is_constructible_v<value_type, initializer_list<_Up>&, _Args...> > > 766cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _Tp& emplace(initializer_list<_Up> __il, _Args&&... __args) { 7670b57cec5SDimitry Andric reset(); 7685f757f3fSDimitry Andric this->__construct(__il, std::forward<_Args>(__args)...); 7690b57cec5SDimitry Andric return this->__get(); 7700b57cec5SDimitry Andric } 7710b57cec5SDimitry Andric 772cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void 773cb14a3feSDimitry Andric swap(optional& __opt) noexcept(is_nothrow_move_constructible_v<value_type> && is_nothrow_swappable_v<value_type>) { 774cb14a3feSDimitry Andric if (this->has_value() == __opt.has_value()) { 7755f757f3fSDimitry Andric using std::swap; 7760b57cec5SDimitry Andric if (this->has_value()) 7770b57cec5SDimitry Andric swap(this->__get(), __opt.__get()); 778cb14a3feSDimitry Andric } else { 779cb14a3feSDimitry Andric if (this->has_value()) { 7805f757f3fSDimitry Andric __opt.__construct(std::move(this->__get())); 7810b57cec5SDimitry Andric reset(); 782cb14a3feSDimitry Andric } else { 7835f757f3fSDimitry Andric this->__construct(std::move(__opt.__get())); 7840b57cec5SDimitry Andric __opt.reset(); 7850b57cec5SDimitry Andric } 7860b57cec5SDimitry Andric } 7870b57cec5SDimitry Andric } 7880b57cec5SDimitry Andric 7890fca6ea1SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr add_pointer_t<value_type const> operator->() const noexcept { 79006c3fb27SDimitry Andric _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(this->has_value(), "optional operator-> called on a disengaged value"); 7915f757f3fSDimitry Andric return std::addressof(this->__get()); 7920b57cec5SDimitry Andric } 7930b57cec5SDimitry Andric 7940fca6ea1SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr add_pointer_t<value_type> operator->() noexcept { 79506c3fb27SDimitry Andric _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(this->has_value(), "optional operator-> called on a disengaged value"); 7965f757f3fSDimitry Andric return std::addressof(this->__get()); 7970b57cec5SDimitry Andric } 7980b57cec5SDimitry Andric 799cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr const value_type& operator*() const& noexcept { 80006c3fb27SDimitry Andric _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(this->has_value(), "optional operator* called on a disengaged value"); 8010b57cec5SDimitry Andric return this->__get(); 8020b57cec5SDimitry Andric } 8030b57cec5SDimitry Andric 804cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr value_type& operator*() & noexcept { 80506c3fb27SDimitry Andric _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(this->has_value(), "optional operator* called on a disengaged value"); 8060b57cec5SDimitry Andric return this->__get(); 8070b57cec5SDimitry Andric } 8080b57cec5SDimitry Andric 809cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr value_type&& operator*() && noexcept { 81006c3fb27SDimitry Andric _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(this->has_value(), "optional operator* called on a disengaged value"); 8115f757f3fSDimitry Andric return std::move(this->__get()); 8120b57cec5SDimitry Andric } 8130b57cec5SDimitry Andric 814cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr const value_type&& operator*() const&& noexcept { 81506c3fb27SDimitry Andric _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(this->has_value(), "optional operator* called on a disengaged value"); 8165f757f3fSDimitry Andric return std::move(this->__get()); 8170b57cec5SDimitry Andric } 8180b57cec5SDimitry Andric 819cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr explicit operator bool() const noexcept { return has_value(); } 8200b57cec5SDimitry Andric 8210b57cec5SDimitry Andric using __base::__get; 822cb14a3feSDimitry Andric using __base::has_value; 8230b57cec5SDimitry Andric 824cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS constexpr value_type const& value() const& { 8250b57cec5SDimitry Andric if (!this->has_value()) 8260b57cec5SDimitry Andric __throw_bad_optional_access(); 8270b57cec5SDimitry Andric return this->__get(); 8280b57cec5SDimitry Andric } 8290b57cec5SDimitry Andric 830cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS constexpr value_type& value() & { 8310b57cec5SDimitry Andric if (!this->has_value()) 8320b57cec5SDimitry Andric __throw_bad_optional_access(); 8330b57cec5SDimitry Andric return this->__get(); 8340b57cec5SDimitry Andric } 8350b57cec5SDimitry Andric 836cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS constexpr value_type&& value() && { 8370b57cec5SDimitry Andric if (!this->has_value()) 8380b57cec5SDimitry Andric __throw_bad_optional_access(); 8395f757f3fSDimitry Andric return std::move(this->__get()); 8400b57cec5SDimitry Andric } 8410b57cec5SDimitry Andric 842cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS constexpr value_type const&& value() const&& { 8430b57cec5SDimitry Andric if (!this->has_value()) 8440b57cec5SDimitry Andric __throw_bad_optional_access(); 8455f757f3fSDimitry Andric return std::move(this->__get()); 8460b57cec5SDimitry Andric } 8470b57cec5SDimitry Andric 8480b57cec5SDimitry Andric template <class _Up> 849cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr value_type value_or(_Up&& __v) const& { 850cb14a3feSDimitry Andric static_assert(is_copy_constructible_v<value_type>, "optional<T>::value_or: T must be copy constructible"); 851cb14a3feSDimitry Andric static_assert(is_convertible_v<_Up, value_type>, "optional<T>::value_or: U must be convertible to T"); 852cb14a3feSDimitry Andric return this->has_value() ? this->__get() : static_cast<value_type>(std::forward<_Up>(__v)); 8530b57cec5SDimitry Andric } 8540b57cec5SDimitry Andric 8550b57cec5SDimitry Andric template <class _Up> 856cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr value_type value_or(_Up&& __v) && { 857cb14a3feSDimitry Andric static_assert(is_move_constructible_v<value_type>, "optional<T>::value_or: T must be move constructible"); 858cb14a3feSDimitry Andric static_assert(is_convertible_v<_Up, value_type>, "optional<T>::value_or: U must be convertible to T"); 859cb14a3feSDimitry Andric return this->has_value() ? std::move(this->__get()) : static_cast<value_type>(std::forward<_Up>(__v)); 8600b57cec5SDimitry Andric } 8610b57cec5SDimitry Andric 86206c3fb27SDimitry Andric# if _LIBCPP_STD_VER >= 23 8630eae32dcSDimitry Andric template <class _Func> 864cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS constexpr auto and_then(_Func&& __f) & { 8650eae32dcSDimitry Andric using _Up = invoke_result_t<_Func, value_type&>; 8660eae32dcSDimitry Andric static_assert(__is_std_optional<remove_cvref_t<_Up>>::value, 8670eae32dcSDimitry Andric "Result of f(value()) must be a specialization of std::optional"); 8680eae32dcSDimitry Andric if (*this) 8695f757f3fSDimitry Andric return std::invoke(std::forward<_Func>(__f), value()); 8700eae32dcSDimitry Andric return remove_cvref_t<_Up>(); 8710eae32dcSDimitry Andric } 8720eae32dcSDimitry Andric 8730eae32dcSDimitry Andric template <class _Func> 874cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS constexpr auto and_then(_Func&& __f) const& { 8750eae32dcSDimitry Andric using _Up = invoke_result_t<_Func, const value_type&>; 8760eae32dcSDimitry Andric static_assert(__is_std_optional<remove_cvref_t<_Up>>::value, 8770eae32dcSDimitry Andric "Result of f(value()) must be a specialization of std::optional"); 8780eae32dcSDimitry Andric if (*this) 8795f757f3fSDimitry Andric return std::invoke(std::forward<_Func>(__f), value()); 8800eae32dcSDimitry Andric return remove_cvref_t<_Up>(); 8810eae32dcSDimitry Andric } 8820eae32dcSDimitry Andric 8830eae32dcSDimitry Andric template <class _Func> 884cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS constexpr auto and_then(_Func&& __f) && { 8850eae32dcSDimitry Andric using _Up = invoke_result_t<_Func, value_type&&>; 8860eae32dcSDimitry Andric static_assert(__is_std_optional<remove_cvref_t<_Up>>::value, 8870eae32dcSDimitry Andric "Result of f(std::move(value())) must be a specialization of std::optional"); 8880eae32dcSDimitry Andric if (*this) 8895f757f3fSDimitry Andric return std::invoke(std::forward<_Func>(__f), std::move(value())); 8900eae32dcSDimitry Andric return remove_cvref_t<_Up>(); 8910eae32dcSDimitry Andric } 8920eae32dcSDimitry Andric 8930eae32dcSDimitry Andric template <class _Func> 894cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr auto and_then(_Func&& __f) const&& { 8950eae32dcSDimitry Andric using _Up = invoke_result_t<_Func, const value_type&&>; 8960eae32dcSDimitry Andric static_assert(__is_std_optional<remove_cvref_t<_Up>>::value, 8970eae32dcSDimitry Andric "Result of f(std::move(value())) must be a specialization of std::optional"); 8980eae32dcSDimitry Andric if (*this) 8995f757f3fSDimitry Andric return std::invoke(std::forward<_Func>(__f), std::move(value())); 9000eae32dcSDimitry Andric return remove_cvref_t<_Up>(); 9010eae32dcSDimitry Andric } 9020eae32dcSDimitry Andric 9030eae32dcSDimitry Andric template <class _Func> 904cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS constexpr auto transform(_Func&& __f) & { 9050eae32dcSDimitry Andric using _Up = remove_cv_t<invoke_result_t<_Func, value_type&>>; 9060eae32dcSDimitry Andric static_assert(!is_array_v<_Up>, "Result of f(value()) should not be an Array"); 907cb14a3feSDimitry Andric static_assert(!is_same_v<_Up, in_place_t>, "Result of f(value()) should not be std::in_place_t"); 908cb14a3feSDimitry Andric static_assert(!is_same_v<_Up, nullopt_t>, "Result of f(value()) should not be std::nullopt_t"); 9090eae32dcSDimitry Andric static_assert(is_object_v<_Up>, "Result of f(value()) should be an object type"); 9100eae32dcSDimitry Andric if (*this) 9115f757f3fSDimitry Andric return optional<_Up>(__optional_construct_from_invoke_tag{}, std::forward<_Func>(__f), value()); 9120eae32dcSDimitry Andric return optional<_Up>(); 9130eae32dcSDimitry Andric } 9140eae32dcSDimitry Andric 9150eae32dcSDimitry Andric template <class _Func> 916cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS constexpr auto transform(_Func&& __f) const& { 9170eae32dcSDimitry Andric using _Up = remove_cv_t<invoke_result_t<_Func, const value_type&>>; 9180eae32dcSDimitry Andric static_assert(!is_array_v<_Up>, "Result of f(value()) should not be an Array"); 919cb14a3feSDimitry Andric static_assert(!is_same_v<_Up, in_place_t>, "Result of f(value()) should not be std::in_place_t"); 920cb14a3feSDimitry Andric static_assert(!is_same_v<_Up, nullopt_t>, "Result of f(value()) should not be std::nullopt_t"); 9210eae32dcSDimitry Andric static_assert(is_object_v<_Up>, "Result of f(value()) should be an object type"); 9220eae32dcSDimitry Andric if (*this) 9235f757f3fSDimitry Andric return optional<_Up>(__optional_construct_from_invoke_tag{}, std::forward<_Func>(__f), value()); 9240eae32dcSDimitry Andric return optional<_Up>(); 9250eae32dcSDimitry Andric } 9260eae32dcSDimitry Andric 9270eae32dcSDimitry Andric template <class _Func> 928cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS constexpr auto transform(_Func&& __f) && { 9290eae32dcSDimitry Andric using _Up = remove_cv_t<invoke_result_t<_Func, value_type&&>>; 9300eae32dcSDimitry Andric static_assert(!is_array_v<_Up>, "Result of f(std::move(value())) should not be an Array"); 931cb14a3feSDimitry Andric static_assert(!is_same_v<_Up, in_place_t>, "Result of f(std::move(value())) should not be std::in_place_t"); 932cb14a3feSDimitry Andric static_assert(!is_same_v<_Up, nullopt_t>, "Result of f(std::move(value())) should not be std::nullopt_t"); 9330eae32dcSDimitry Andric static_assert(is_object_v<_Up>, "Result of f(std::move(value())) should be an object type"); 9340eae32dcSDimitry Andric if (*this) 9355f757f3fSDimitry Andric return optional<_Up>(__optional_construct_from_invoke_tag{}, std::forward<_Func>(__f), std::move(value())); 9360eae32dcSDimitry Andric return optional<_Up>(); 9370eae32dcSDimitry Andric } 9380eae32dcSDimitry Andric 9390eae32dcSDimitry Andric template <class _Func> 940cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS constexpr auto transform(_Func&& __f) const&& { 9410eae32dcSDimitry Andric using _Up = remove_cvref_t<invoke_result_t<_Func, const value_type&&>>; 9420eae32dcSDimitry Andric static_assert(!is_array_v<_Up>, "Result of f(std::move(value())) should not be an Array"); 943cb14a3feSDimitry Andric static_assert(!is_same_v<_Up, in_place_t>, "Result of f(std::move(value())) should not be std::in_place_t"); 944cb14a3feSDimitry Andric static_assert(!is_same_v<_Up, nullopt_t>, "Result of f(std::move(value())) should not be std::nullopt_t"); 9450eae32dcSDimitry Andric static_assert(is_object_v<_Up>, "Result of f(std::move(value())) should be an object type"); 9460eae32dcSDimitry Andric if (*this) 9475f757f3fSDimitry Andric return optional<_Up>(__optional_construct_from_invoke_tag{}, std::forward<_Func>(__f), std::move(value())); 9480eae32dcSDimitry Andric return optional<_Up>(); 9490eae32dcSDimitry Andric } 9500eae32dcSDimitry Andric 9510eae32dcSDimitry Andric template <invocable _Func> 952cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr optional or_else(_Func&& __f) const& 953cb14a3feSDimitry Andric requires is_copy_constructible_v<value_type> 954cb14a3feSDimitry Andric { 9550eae32dcSDimitry Andric static_assert(is_same_v<remove_cvref_t<invoke_result_t<_Func>>, optional>, 9560eae32dcSDimitry Andric "Result of f() should be the same type as this optional"); 9570eae32dcSDimitry Andric if (*this) 9580eae32dcSDimitry Andric return *this; 9595f757f3fSDimitry Andric return std::forward<_Func>(__f)(); 9600eae32dcSDimitry Andric } 9610eae32dcSDimitry Andric 9620eae32dcSDimitry Andric template <invocable _Func> 963cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr optional or_else(_Func&& __f) && 964cb14a3feSDimitry Andric requires is_move_constructible_v<value_type> 965cb14a3feSDimitry Andric { 9660eae32dcSDimitry Andric static_assert(is_same_v<remove_cvref_t<invoke_result_t<_Func>>, optional>, 9670eae32dcSDimitry Andric "Result of f() should be the same type as this optional"); 9680eae32dcSDimitry Andric if (*this) 9695f757f3fSDimitry Andric return std::move(*this); 9705f757f3fSDimitry Andric return std::forward<_Func>(__f)(); 9710eae32dcSDimitry Andric } 97206c3fb27SDimitry Andric# endif // _LIBCPP_STD_VER >= 23 9730eae32dcSDimitry Andric 9740b57cec5SDimitry Andric using __base::reset; 9750b57cec5SDimitry Andric}; 9760b57cec5SDimitry Andric 977349cc55cSDimitry Andric# if _LIBCPP_STD_VER >= 17 97804eeddc0SDimitry Andrictemplate <class _Tp> 97904eeddc0SDimitry Andricoptional(_Tp) -> optional<_Tp>; 9800b57cec5SDimitry Andric# endif 9810b57cec5SDimitry Andric 9820b57cec5SDimitry Andric// Comparisons between optionals 9830b57cec5SDimitry Andrictemplate <class _Tp, class _Up> 984cb14a3feSDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr enable_if_t< 985cb14a3feSDimitry Andric is_convertible_v<decltype(std::declval<const _Tp&>() == std::declval<const _Up&>()), bool>, 986cb14a3feSDimitry Andric bool > 987cb14a3feSDimitry Andricoperator==(const optional<_Tp>& __x, const optional<_Up>& __y) { 9880b57cec5SDimitry Andric if (static_cast<bool>(__x) != static_cast<bool>(__y)) 9890b57cec5SDimitry Andric return false; 9900b57cec5SDimitry Andric if (!static_cast<bool>(__x)) 9910b57cec5SDimitry Andric return true; 9920b57cec5SDimitry Andric return *__x == *__y; 9930b57cec5SDimitry Andric} 9940b57cec5SDimitry Andric 9950b57cec5SDimitry Andrictemplate <class _Tp, class _Up> 996cb14a3feSDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr enable_if_t< 997cb14a3feSDimitry Andric is_convertible_v<decltype(std::declval<const _Tp&>() != std::declval<const _Up&>()), bool>, 998cb14a3feSDimitry Andric bool > 999cb14a3feSDimitry Andricoperator!=(const optional<_Tp>& __x, const optional<_Up>& __y) { 10000b57cec5SDimitry Andric if (static_cast<bool>(__x) != static_cast<bool>(__y)) 10010b57cec5SDimitry Andric return true; 10020b57cec5SDimitry Andric if (!static_cast<bool>(__x)) 10030b57cec5SDimitry Andric return false; 10040b57cec5SDimitry Andric return *__x != *__y; 10050b57cec5SDimitry Andric} 10060b57cec5SDimitry Andric 10070b57cec5SDimitry Andrictemplate <class _Tp, class _Up> 1008cb14a3feSDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr enable_if_t< 1009cb14a3feSDimitry Andric is_convertible_v<decltype(std::declval<const _Tp&>() < std::declval<const _Up&>()), bool>, 1010cb14a3feSDimitry Andric bool > 1011cb14a3feSDimitry Andricoperator<(const optional<_Tp>& __x, const optional<_Up>& __y) { 10120b57cec5SDimitry Andric if (!static_cast<bool>(__y)) 10130b57cec5SDimitry Andric return false; 10140b57cec5SDimitry Andric if (!static_cast<bool>(__x)) 10150b57cec5SDimitry Andric return true; 10160b57cec5SDimitry Andric return *__x < *__y; 10170b57cec5SDimitry Andric} 10180b57cec5SDimitry Andric 10190b57cec5SDimitry Andrictemplate <class _Tp, class _Up> 1020cb14a3feSDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr enable_if_t< 1021cb14a3feSDimitry Andric is_convertible_v<decltype(std::declval<const _Tp&>() > std::declval<const _Up&>()), bool>, 1022cb14a3feSDimitry Andric bool > 1023cb14a3feSDimitry Andricoperator>(const optional<_Tp>& __x, const optional<_Up>& __y) { 10240b57cec5SDimitry Andric if (!static_cast<bool>(__x)) 10250b57cec5SDimitry Andric return false; 10260b57cec5SDimitry Andric if (!static_cast<bool>(__y)) 10270b57cec5SDimitry Andric return true; 10280b57cec5SDimitry Andric return *__x > *__y; 10290b57cec5SDimitry Andric} 10300b57cec5SDimitry Andric 10310b57cec5SDimitry Andrictemplate <class _Tp, class _Up> 1032cb14a3feSDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr enable_if_t< 1033cb14a3feSDimitry Andric is_convertible_v<decltype(std::declval<const _Tp&>() <= std::declval<const _Up&>()), bool>, 1034cb14a3feSDimitry Andric bool > 1035cb14a3feSDimitry Andricoperator<=(const optional<_Tp>& __x, const optional<_Up>& __y) { 10360b57cec5SDimitry Andric if (!static_cast<bool>(__x)) 10370b57cec5SDimitry Andric return true; 10380b57cec5SDimitry Andric if (!static_cast<bool>(__y)) 10390b57cec5SDimitry Andric return false; 10400b57cec5SDimitry Andric return *__x <= *__y; 10410b57cec5SDimitry Andric} 10420b57cec5SDimitry Andric 10430b57cec5SDimitry Andrictemplate <class _Tp, class _Up> 1044cb14a3feSDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr enable_if_t< 1045cb14a3feSDimitry Andric is_convertible_v<decltype(std::declval<const _Tp&>() >= std::declval<const _Up&>()), bool>, 1046cb14a3feSDimitry Andric bool > 1047cb14a3feSDimitry Andricoperator>=(const optional<_Tp>& __x, const optional<_Up>& __y) { 10480b57cec5SDimitry Andric if (!static_cast<bool>(__y)) 10490b57cec5SDimitry Andric return true; 10500b57cec5SDimitry Andric if (!static_cast<bool>(__x)) 10510b57cec5SDimitry Andric return false; 10520b57cec5SDimitry Andric return *__x >= *__y; 10530b57cec5SDimitry Andric} 10540b57cec5SDimitry Andric 105506c3fb27SDimitry Andric# if _LIBCPP_STD_VER >= 20 105606c3fb27SDimitry Andric 105706c3fb27SDimitry Andrictemplate <class _Tp, three_way_comparable_with<_Tp> _Up> 105806c3fb27SDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr compare_three_way_result_t<_Tp, _Up> 105906c3fb27SDimitry Andricoperator<=>(const optional<_Tp>& __x, const optional<_Up>& __y) { 106006c3fb27SDimitry Andric if (__x && __y) 106106c3fb27SDimitry Andric return *__x <=> *__y; 106206c3fb27SDimitry Andric return __x.has_value() <=> __y.has_value(); 106306c3fb27SDimitry Andric} 106406c3fb27SDimitry Andric 106506c3fb27SDimitry Andric# endif // _LIBCPP_STD_VER >= 20 106606c3fb27SDimitry Andric 10670b57cec5SDimitry Andric// Comparisons with nullopt 10680b57cec5SDimitry Andrictemplate <class _Tp> 1069cb14a3feSDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr bool operator==(const optional<_Tp>& __x, nullopt_t) noexcept { 10700b57cec5SDimitry Andric return !static_cast<bool>(__x); 10710b57cec5SDimitry Andric} 10720b57cec5SDimitry Andric 107306c3fb27SDimitry Andric# if _LIBCPP_STD_VER <= 17 107406c3fb27SDimitry Andric 10750b57cec5SDimitry Andrictemplate <class _Tp> 1076cb14a3feSDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr bool operator==(nullopt_t, const optional<_Tp>& __x) noexcept { 10770b57cec5SDimitry Andric return !static_cast<bool>(__x); 10780b57cec5SDimitry Andric} 10790b57cec5SDimitry Andric 10800b57cec5SDimitry Andrictemplate <class _Tp> 1081cb14a3feSDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr bool operator!=(const optional<_Tp>& __x, nullopt_t) noexcept { 10820b57cec5SDimitry Andric return static_cast<bool>(__x); 10830b57cec5SDimitry Andric} 10840b57cec5SDimitry Andric 10850b57cec5SDimitry Andrictemplate <class _Tp> 1086cb14a3feSDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr bool operator!=(nullopt_t, const optional<_Tp>& __x) noexcept { 10870b57cec5SDimitry Andric return static_cast<bool>(__x); 10880b57cec5SDimitry Andric} 10890b57cec5SDimitry Andric 10900b57cec5SDimitry Andrictemplate <class _Tp> 1091cb14a3feSDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr bool operator<(const optional<_Tp>&, nullopt_t) noexcept { 10920b57cec5SDimitry Andric return false; 10930b57cec5SDimitry Andric} 10940b57cec5SDimitry Andric 10950b57cec5SDimitry Andrictemplate <class _Tp> 1096cb14a3feSDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr bool operator<(nullopt_t, const optional<_Tp>& __x) noexcept { 10970b57cec5SDimitry Andric return static_cast<bool>(__x); 10980b57cec5SDimitry Andric} 10990b57cec5SDimitry Andric 11000b57cec5SDimitry Andrictemplate <class _Tp> 1101cb14a3feSDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr bool operator<=(const optional<_Tp>& __x, nullopt_t) noexcept { 11020b57cec5SDimitry Andric return !static_cast<bool>(__x); 11030b57cec5SDimitry Andric} 11040b57cec5SDimitry Andric 11050b57cec5SDimitry Andrictemplate <class _Tp> 1106cb14a3feSDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr bool operator<=(nullopt_t, const optional<_Tp>&) noexcept { 11070b57cec5SDimitry Andric return true; 11080b57cec5SDimitry Andric} 11090b57cec5SDimitry Andric 11100b57cec5SDimitry Andrictemplate <class _Tp> 1111cb14a3feSDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr bool operator>(const optional<_Tp>& __x, nullopt_t) noexcept { 11120b57cec5SDimitry Andric return static_cast<bool>(__x); 11130b57cec5SDimitry Andric} 11140b57cec5SDimitry Andric 11150b57cec5SDimitry Andrictemplate <class _Tp> 1116cb14a3feSDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr bool operator>(nullopt_t, const optional<_Tp>&) noexcept { 11170b57cec5SDimitry Andric return false; 11180b57cec5SDimitry Andric} 11190b57cec5SDimitry Andric 11200b57cec5SDimitry Andrictemplate <class _Tp> 1121cb14a3feSDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr bool operator>=(const optional<_Tp>&, nullopt_t) noexcept { 11220b57cec5SDimitry Andric return true; 11230b57cec5SDimitry Andric} 11240b57cec5SDimitry Andric 11250b57cec5SDimitry Andrictemplate <class _Tp> 1126cb14a3feSDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr bool operator>=(nullopt_t, const optional<_Tp>& __x) noexcept { 11270b57cec5SDimitry Andric return !static_cast<bool>(__x); 11280b57cec5SDimitry Andric} 11290b57cec5SDimitry Andric 113006c3fb27SDimitry Andric# else // _LIBCPP_STD_VER <= 17 113106c3fb27SDimitry Andric 113206c3fb27SDimitry Andrictemplate <class _Tp> 113306c3fb27SDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr strong_ordering operator<=>(const optional<_Tp>& __x, nullopt_t) noexcept { 113406c3fb27SDimitry Andric return __x.has_value() <=> false; 113506c3fb27SDimitry Andric} 113606c3fb27SDimitry Andric 113706c3fb27SDimitry Andric# endif // _LIBCPP_STD_VER <= 17 113806c3fb27SDimitry Andric 11390b57cec5SDimitry Andric// Comparisons with T 11400b57cec5SDimitry Andrictemplate <class _Tp, class _Up> 1141cb14a3feSDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr enable_if_t< 1142cb14a3feSDimitry Andric is_convertible_v<decltype(std::declval<const _Tp&>() == std::declval<const _Up&>()), bool>, 1143cb14a3feSDimitry Andric bool > 1144cb14a3feSDimitry Andricoperator==(const optional<_Tp>& __x, const _Up& __v) { 11450b57cec5SDimitry Andric return static_cast<bool>(__x) ? *__x == __v : false; 11460b57cec5SDimitry Andric} 11470b57cec5SDimitry Andric 11480b57cec5SDimitry Andrictemplate <class _Tp, class _Up> 1149cb14a3feSDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr enable_if_t< 1150cb14a3feSDimitry Andric is_convertible_v<decltype(std::declval<const _Tp&>() == std::declval<const _Up&>()), bool>, 1151cb14a3feSDimitry Andric bool > 1152cb14a3feSDimitry Andricoperator==(const _Tp& __v, const optional<_Up>& __x) { 11530b57cec5SDimitry Andric return static_cast<bool>(__x) ? __v == *__x : false; 11540b57cec5SDimitry Andric} 11550b57cec5SDimitry Andric 11560b57cec5SDimitry Andrictemplate <class _Tp, class _Up> 1157cb14a3feSDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr enable_if_t< 1158cb14a3feSDimitry Andric is_convertible_v<decltype(std::declval<const _Tp&>() != std::declval<const _Up&>()), bool>, 1159cb14a3feSDimitry Andric bool > 1160cb14a3feSDimitry Andricoperator!=(const optional<_Tp>& __x, const _Up& __v) { 11610b57cec5SDimitry Andric return static_cast<bool>(__x) ? *__x != __v : true; 11620b57cec5SDimitry Andric} 11630b57cec5SDimitry Andric 11640b57cec5SDimitry Andrictemplate <class _Tp, class _Up> 1165cb14a3feSDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr enable_if_t< 1166cb14a3feSDimitry Andric is_convertible_v<decltype(std::declval<const _Tp&>() != std::declval<const _Up&>()), bool>, 1167cb14a3feSDimitry Andric bool > 1168cb14a3feSDimitry Andricoperator!=(const _Tp& __v, const optional<_Up>& __x) { 11690b57cec5SDimitry Andric return static_cast<bool>(__x) ? __v != *__x : true; 11700b57cec5SDimitry Andric} 11710b57cec5SDimitry Andric 11720b57cec5SDimitry Andrictemplate <class _Tp, class _Up> 1173cb14a3feSDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr enable_if_t< 1174cb14a3feSDimitry Andric is_convertible_v<decltype(std::declval<const _Tp&>() < std::declval<const _Up&>()), bool>, 1175cb14a3feSDimitry Andric bool > 1176cb14a3feSDimitry Andricoperator<(const optional<_Tp>& __x, const _Up& __v) { 11770b57cec5SDimitry Andric return static_cast<bool>(__x) ? *__x < __v : true; 11780b57cec5SDimitry Andric} 11790b57cec5SDimitry Andric 11800b57cec5SDimitry Andrictemplate <class _Tp, class _Up> 1181cb14a3feSDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr enable_if_t< 1182cb14a3feSDimitry Andric is_convertible_v<decltype(std::declval<const _Tp&>() < std::declval<const _Up&>()), bool>, 1183cb14a3feSDimitry Andric bool > 1184cb14a3feSDimitry Andricoperator<(const _Tp& __v, const optional<_Up>& __x) { 11850b57cec5SDimitry Andric return static_cast<bool>(__x) ? __v < *__x : false; 11860b57cec5SDimitry Andric} 11870b57cec5SDimitry Andric 11880b57cec5SDimitry Andrictemplate <class _Tp, class _Up> 1189cb14a3feSDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr enable_if_t< 1190cb14a3feSDimitry Andric is_convertible_v<decltype(std::declval<const _Tp&>() <= std::declval<const _Up&>()), bool>, 1191cb14a3feSDimitry Andric bool > 1192cb14a3feSDimitry Andricoperator<=(const optional<_Tp>& __x, const _Up& __v) { 11930b57cec5SDimitry Andric return static_cast<bool>(__x) ? *__x <= __v : true; 11940b57cec5SDimitry Andric} 11950b57cec5SDimitry Andric 11960b57cec5SDimitry Andrictemplate <class _Tp, class _Up> 1197cb14a3feSDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr enable_if_t< 1198cb14a3feSDimitry Andric is_convertible_v<decltype(std::declval<const _Tp&>() <= std::declval<const _Up&>()), bool>, 1199cb14a3feSDimitry Andric bool > 1200cb14a3feSDimitry Andricoperator<=(const _Tp& __v, const optional<_Up>& __x) { 12010b57cec5SDimitry Andric return static_cast<bool>(__x) ? __v <= *__x : false; 12020b57cec5SDimitry Andric} 12030b57cec5SDimitry Andric 12040b57cec5SDimitry Andrictemplate <class _Tp, class _Up> 1205cb14a3feSDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr enable_if_t< 1206cb14a3feSDimitry Andric is_convertible_v<decltype(std::declval<const _Tp&>() > std::declval<const _Up&>()), bool>, 1207cb14a3feSDimitry Andric bool > 1208cb14a3feSDimitry Andricoperator>(const optional<_Tp>& __x, const _Up& __v) { 12090b57cec5SDimitry Andric return static_cast<bool>(__x) ? *__x > __v : false; 12100b57cec5SDimitry Andric} 12110b57cec5SDimitry Andric 12120b57cec5SDimitry Andrictemplate <class _Tp, class _Up> 1213cb14a3feSDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr enable_if_t< 1214cb14a3feSDimitry Andric is_convertible_v<decltype(std::declval<const _Tp&>() > std::declval<const _Up&>()), bool>, 1215cb14a3feSDimitry Andric bool > 1216cb14a3feSDimitry Andricoperator>(const _Tp& __v, const optional<_Up>& __x) { 12170b57cec5SDimitry Andric return static_cast<bool>(__x) ? __v > *__x : true; 12180b57cec5SDimitry Andric} 12190b57cec5SDimitry Andric 12200b57cec5SDimitry Andrictemplate <class _Tp, class _Up> 1221cb14a3feSDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr enable_if_t< 1222cb14a3feSDimitry Andric is_convertible_v<decltype(std::declval<const _Tp&>() >= std::declval<const _Up&>()), bool>, 1223cb14a3feSDimitry Andric bool > 1224cb14a3feSDimitry Andricoperator>=(const optional<_Tp>& __x, const _Up& __v) { 12250b57cec5SDimitry Andric return static_cast<bool>(__x) ? *__x >= __v : false; 12260b57cec5SDimitry Andric} 12270b57cec5SDimitry Andric 12280b57cec5SDimitry Andrictemplate <class _Tp, class _Up> 1229cb14a3feSDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr enable_if_t< 1230cb14a3feSDimitry Andric is_convertible_v<decltype(std::declval<const _Tp&>() >= std::declval<const _Up&>()), bool>, 1231cb14a3feSDimitry Andric bool > 1232cb14a3feSDimitry Andricoperator>=(const _Tp& __v, const optional<_Up>& __x) { 12330b57cec5SDimitry Andric return static_cast<bool>(__x) ? __v >= *__x : true; 12340b57cec5SDimitry Andric} 12350b57cec5SDimitry Andric 123606c3fb27SDimitry Andric# if _LIBCPP_STD_VER >= 20 123706c3fb27SDimitry Andric 123806c3fb27SDimitry Andrictemplate <class _Tp, class _Up> 123906c3fb27SDimitry Andric requires(!__is_derived_from_optional<_Up>) && three_way_comparable_with<_Tp, _Up> 124006c3fb27SDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr compare_three_way_result_t<_Tp, _Up> 124106c3fb27SDimitry Andricoperator<=>(const optional<_Tp>& __x, const _Up& __v) { 124206c3fb27SDimitry Andric return __x.has_value() ? *__x <=> __v : strong_ordering::less; 124306c3fb27SDimitry Andric} 124406c3fb27SDimitry Andric 124506c3fb27SDimitry Andric# endif // _LIBCPP_STD_VER >= 20 124606c3fb27SDimitry Andric 12470b57cec5SDimitry Andrictemplate <class _Tp> 12480fca6ea1SDimitry Andricinline _LIBCPP_HIDE_FROM_ABI 12490fca6ea1SDimitry Andric_LIBCPP_CONSTEXPR_SINCE_CXX20 enable_if_t< is_move_constructible_v<_Tp> && is_swappable_v<_Tp>, void > 1250cb14a3feSDimitry Andricswap(optional<_Tp>& __x, optional<_Tp>& __y) noexcept(noexcept(__x.swap(__y))) { 12510b57cec5SDimitry Andric __x.swap(__y); 12520b57cec5SDimitry Andric} 12530b57cec5SDimitry Andric 12540b57cec5SDimitry Andrictemplate <class _Tp> 1255cb14a3feSDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr optional<decay_t<_Tp>> make_optional(_Tp&& __v) { 12565f757f3fSDimitry Andric return optional<decay_t<_Tp>>(std::forward<_Tp>(__v)); 12570b57cec5SDimitry Andric} 12580b57cec5SDimitry Andric 12590b57cec5SDimitry Andrictemplate <class _Tp, class... _Args> 1260cb14a3feSDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr optional<_Tp> make_optional(_Args&&... __args) { 12615f757f3fSDimitry Andric return optional<_Tp>(in_place, std::forward<_Args>(__args)...); 12620b57cec5SDimitry Andric} 12630b57cec5SDimitry Andric 12640b57cec5SDimitry Andrictemplate <class _Tp, class _Up, class... _Args> 1265cb14a3feSDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr optional<_Tp> make_optional(initializer_list<_Up> __il, _Args&&... __args) { 12665f757f3fSDimitry Andric return optional<_Tp>(in_place, __il, std::forward<_Args>(__args)...); 12670b57cec5SDimitry Andric} 12680b57cec5SDimitry Andric 12690b57cec5SDimitry Andrictemplate <class _Tp> 1270cb14a3feSDimitry Andricstruct _LIBCPP_TEMPLATE_VIS hash< __enable_hash_helper<optional<_Tp>, remove_const_t<_Tp>> > { 1271fe6060f1SDimitry Andric# if _LIBCPP_STD_VER <= 17 || defined(_LIBCPP_ENABLE_CXX20_REMOVED_BINDER_TYPEDEFS) 1272fe6060f1SDimitry Andric _LIBCPP_DEPRECATED_IN_CXX17 typedef optional<_Tp> argument_type; 1273fe6060f1SDimitry Andric _LIBCPP_DEPRECATED_IN_CXX17 typedef size_t result_type; 1274fe6060f1SDimitry Andric# endif 12750b57cec5SDimitry Andric 1276cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI size_t operator()(const optional<_Tp>& __opt) const { 12770b57cec5SDimitry Andric return static_cast<bool>(__opt) ? hash<remove_const_t<_Tp>>()(*__opt) : 0; 12780b57cec5SDimitry Andric } 12790b57cec5SDimitry Andric}; 12800b57cec5SDimitry Andric 12810b57cec5SDimitry Andric_LIBCPP_END_NAMESPACE_STD 12820b57cec5SDimitry Andric 128306c3fb27SDimitry Andric#endif // _LIBCPP_STD_VER >= 17 128406c3fb27SDimitry Andric 128506c3fb27SDimitry Andric_LIBCPP_POP_MACROS 12860b57cec5SDimitry Andric 1287bdd1243dSDimitry Andric#if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER <= 20 1288bdd1243dSDimitry Andric# include <atomic> 1289bdd1243dSDimitry Andric# include <climits> 1290bdd1243dSDimitry Andric# include <concepts> 1291bdd1243dSDimitry Andric# include <ctime> 1292bdd1243dSDimitry Andric# include <iterator> 12930fca6ea1SDimitry Andric# include <limits> 1294bdd1243dSDimitry Andric# include <memory> 1295bdd1243dSDimitry Andric# include <ratio> 12965f757f3fSDimitry Andric# include <stdexcept> 1297bdd1243dSDimitry Andric# include <tuple> 129806c3fb27SDimitry Andric# include <type_traits> 1299bdd1243dSDimitry Andric# include <typeinfo> 1300bdd1243dSDimitry Andric# include <utility> 1301bdd1243dSDimitry Andric# include <variant> 1302bdd1243dSDimitry Andric#endif 1303bdd1243dSDimitry Andric 13040b57cec5SDimitry Andric#endif // _LIBCPP_OPTIONAL 1305