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 1390b57cec5SDimitry Andric constexpr T const *operator->() const; 1400b57cec5SDimitry Andric constexpr T *operator->(); 1410b57cec5SDimitry Andric constexpr T const &operator*() const &; 1420b57cec5SDimitry Andric constexpr T &operator*() &; 1430b57cec5SDimitry Andric constexpr T &&operator*() &&; 1440b57cec5SDimitry Andric constexpr const T &&operator*() const &&; 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 18081ad6265SDimitry Andric#include <__assert> // all public C++ headers provide the assertion handler 181e8d8bef9SDimitry Andric#include <__availability> 18206c3fb27SDimitry Andric#include <__compare/compare_three_way_result.h> 18306c3fb27SDimitry Andric#include <__compare/three_way_comparable.h> 1840eae32dcSDimitry Andric#include <__concepts/invocable.h> 185fe6060f1SDimitry Andric#include <__config> 1865f757f3fSDimitry Andric#include <__exception/exception.h> 18781ad6265SDimitry Andric#include <__functional/hash.h> 18881ad6265SDimitry Andric#include <__functional/invoke.h> 18906c3fb27SDimitry Andric#include <__functional/reference_wrapper.h> 19081ad6265SDimitry Andric#include <__functional/unary_function.h> 19106c3fb27SDimitry Andric#include <__memory/addressof.h> 19281ad6265SDimitry Andric#include <__memory/construct_at.h> 19306c3fb27SDimitry Andric#include <__tuple/sfinae_helpers.h> 19406c3fb27SDimitry Andric#include <__type_traits/add_pointer.h> 19506c3fb27SDimitry Andric#include <__type_traits/conditional.h> 19606c3fb27SDimitry Andric#include <__type_traits/conjunction.h> 19706c3fb27SDimitry Andric#include <__type_traits/decay.h> 19806c3fb27SDimitry Andric#include <__type_traits/disjunction.h> 19906c3fb27SDimitry Andric#include <__type_traits/is_array.h> 20006c3fb27SDimitry Andric#include <__type_traits/is_assignable.h> 20106c3fb27SDimitry Andric#include <__type_traits/is_constructible.h> 20206c3fb27SDimitry Andric#include <__type_traits/is_convertible.h> 20306c3fb27SDimitry Andric#include <__type_traits/is_copy_assignable.h> 20406c3fb27SDimitry Andric#include <__type_traits/is_copy_constructible.h> 20506c3fb27SDimitry Andric#include <__type_traits/is_destructible.h> 20606c3fb27SDimitry Andric#include <__type_traits/is_move_assignable.h> 20706c3fb27SDimitry Andric#include <__type_traits/is_move_constructible.h> 20806c3fb27SDimitry Andric#include <__type_traits/is_nothrow_move_assignable.h> 20906c3fb27SDimitry Andric#include <__type_traits/is_nothrow_move_constructible.h> 21006c3fb27SDimitry Andric#include <__type_traits/is_object.h> 21106c3fb27SDimitry Andric#include <__type_traits/is_reference.h> 21206c3fb27SDimitry Andric#include <__type_traits/is_scalar.h> 21306c3fb27SDimitry Andric#include <__type_traits/is_swappable.h> 21406c3fb27SDimitry Andric#include <__type_traits/is_trivially_copy_assignable.h> 21506c3fb27SDimitry Andric#include <__type_traits/is_trivially_copy_constructible.h> 21606c3fb27SDimitry Andric#include <__type_traits/is_trivially_destructible.h> 21706c3fb27SDimitry Andric#include <__type_traits/is_trivially_move_assignable.h> 21806c3fb27SDimitry Andric#include <__type_traits/is_trivially_move_constructible.h> 21906c3fb27SDimitry Andric#include <__type_traits/negation.h> 22006c3fb27SDimitry Andric#include <__type_traits/remove_const.h> 22106c3fb27SDimitry Andric#include <__type_traits/remove_cvref.h> 22206c3fb27SDimitry Andric#include <__type_traits/remove_reference.h> 22306c3fb27SDimitry Andric#include <__utility/declval.h> 22481ad6265SDimitry Andric#include <__utility/forward.h> 22581ad6265SDimitry Andric#include <__utility/in_place.h> 22681ad6265SDimitry Andric#include <__utility/move.h> 22781ad6265SDimitry Andric#include <__utility/swap.h> 22806c3fb27SDimitry Andric#include <__verbose_abort> 2290b57cec5SDimitry Andric#include <initializer_list> 2300b57cec5SDimitry Andric#include <new> 2310b57cec5SDimitry Andric#include <version> 2320b57cec5SDimitry Andric 23381ad6265SDimitry Andric// standard-mandated includes 234bdd1243dSDimitry Andric 235bdd1243dSDimitry Andric// [optional.syn] 23681ad6265SDimitry Andric#include <compare> 23781ad6265SDimitry Andric 2380b57cec5SDimitry Andric#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 2390b57cec5SDimitry Andric# pragma GCC system_header 2400b57cec5SDimitry Andric#endif 2410b57cec5SDimitry Andric 24206c3fb27SDimitry Andric_LIBCPP_PUSH_MACROS 24306c3fb27SDimitry Andric#include <__undef_macros> 24406c3fb27SDimitry Andric 2450b57cec5SDimitry Andricnamespace std // purposefully not using versioning namespace 2460b57cec5SDimitry Andric{ 2470b57cec5SDimitry Andric 248*cb14a3feSDimitry Andricclass _LIBCPP_EXPORTED_FROM_ABI _LIBCPP_AVAILABILITY_BAD_OPTIONAL_ACCESS bad_optional_access : public exception { 2490b57cec5SDimitry Andricpublic: 2505f757f3fSDimitry Andric _LIBCPP_HIDE_FROM_ABI bad_optional_access() _NOEXCEPT = default; 2515f757f3fSDimitry Andric _LIBCPP_HIDE_FROM_ABI bad_optional_access(const bad_optional_access&) _NOEXCEPT = default; 2525f757f3fSDimitry Andric _LIBCPP_HIDE_FROM_ABI bad_optional_access& operator=(const bad_optional_access&) _NOEXCEPT = default; 2530b57cec5SDimitry Andric // Get the key function ~bad_optional_access() into the dylib 254bdd1243dSDimitry Andric ~bad_optional_access() _NOEXCEPT override; 255bdd1243dSDimitry Andric const char* what() const _NOEXCEPT override; 2560b57cec5SDimitry Andric}; 2570b57cec5SDimitry Andric 2580eae32dcSDimitry Andric} // namespace std 2590b57cec5SDimitry Andric 26006c3fb27SDimitry Andric#if _LIBCPP_STD_VER >= 17 2610b57cec5SDimitry Andric 2620b57cec5SDimitry Andric_LIBCPP_BEGIN_NAMESPACE_STD 2630b57cec5SDimitry Andric 264*cb14a3feSDimitry Andric_LIBCPP_NORETURN inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS void 265*cb14a3feSDimitry Andric__throw_bad_optional_access() { 26606c3fb27SDimitry Andric# ifndef _LIBCPP_HAS_NO_EXCEPTIONS 2670b57cec5SDimitry Andric throw bad_optional_access(); 2680b57cec5SDimitry Andric# else 26906c3fb27SDimitry Andric _LIBCPP_VERBOSE_ABORT("bad_optional_access was thrown in -fno-exceptions mode"); 2700b57cec5SDimitry Andric# endif 2710b57cec5SDimitry Andric} 2720b57cec5SDimitry Andric 273*cb14a3feSDimitry Andricstruct nullopt_t { 274*cb14a3feSDimitry Andric struct __secret_tag { 275*cb14a3feSDimitry Andric explicit __secret_tag() = default; 276*cb14a3feSDimitry Andric }; 2775f757f3fSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr explicit nullopt_t(__secret_tag, __secret_tag) noexcept {} 2780b57cec5SDimitry Andric}; 2790b57cec5SDimitry Andric 280349cc55cSDimitry Andricinline constexpr nullopt_t nullopt{nullopt_t::__secret_tag{}, nullopt_t::__secret_tag{}}; 2810b57cec5SDimitry Andric 2820eae32dcSDimitry Andricstruct __optional_construct_from_invoke_tag {}; 2830eae32dcSDimitry Andric 2840b57cec5SDimitry Andrictemplate <class _Tp, bool = is_trivially_destructible<_Tp>::value> 2850b57cec5SDimitry Andricstruct __optional_destruct_base; 2860b57cec5SDimitry Andric 2870b57cec5SDimitry Andrictemplate <class _Tp> 288*cb14a3feSDimitry Andricstruct __optional_destruct_base<_Tp, false> { 2890b57cec5SDimitry Andric typedef _Tp value_type; 290*cb14a3feSDimitry Andric static_assert(is_object_v<value_type>, "instantiation of optional with a non-object type is undefined behavior"); 291*cb14a3feSDimitry Andric union { 2920b57cec5SDimitry Andric char __null_state_; 2930b57cec5SDimitry Andric value_type __val_; 2940b57cec5SDimitry Andric }; 2950b57cec5SDimitry Andric bool __engaged_; 2960b57cec5SDimitry Andric 297*cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 ~__optional_destruct_base() { 2980b57cec5SDimitry Andric if (__engaged_) 2990b57cec5SDimitry Andric __val_.~value_type(); 3000b57cec5SDimitry Andric } 3010b57cec5SDimitry Andric 302*cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr __optional_destruct_base() noexcept : __null_state_(), __engaged_(false) {} 3030b57cec5SDimitry Andric 3040b57cec5SDimitry Andric template <class... _Args> 305*cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr explicit __optional_destruct_base(in_place_t, _Args&&... __args) 306*cb14a3feSDimitry Andric : __val_(std::forward<_Args>(__args)...), __engaged_(true) {} 3070b57cec5SDimitry Andric 30806c3fb27SDimitry Andric# if _LIBCPP_STD_VER >= 23 3090eae32dcSDimitry Andric template <class _Fp, class... _Args> 310*cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr __optional_destruct_base( 311*cb14a3feSDimitry Andric __optional_construct_from_invoke_tag, _Fp&& __f, _Args&&... __args) 3125f757f3fSDimitry Andric : __val_(std::invoke(std::forward<_Fp>(__f), std::forward<_Args>(__args)...)), __engaged_(true) {} 3130eae32dcSDimitry Andric# endif 3140eae32dcSDimitry Andric 315*cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void reset() noexcept { 316*cb14a3feSDimitry Andric if (__engaged_) { 3170b57cec5SDimitry Andric __val_.~value_type(); 3180b57cec5SDimitry Andric __engaged_ = false; 3190b57cec5SDimitry Andric } 3200b57cec5SDimitry Andric } 3210b57cec5SDimitry Andric}; 3220b57cec5SDimitry Andric 3230b57cec5SDimitry Andrictemplate <class _Tp> 324*cb14a3feSDimitry Andricstruct __optional_destruct_base<_Tp, true> { 3250b57cec5SDimitry Andric typedef _Tp value_type; 326*cb14a3feSDimitry Andric static_assert(is_object_v<value_type>, "instantiation of optional with a non-object type is undefined behavior"); 327*cb14a3feSDimitry Andric union { 3280b57cec5SDimitry Andric char __null_state_; 3290b57cec5SDimitry Andric value_type __val_; 3300b57cec5SDimitry Andric }; 3310b57cec5SDimitry Andric bool __engaged_; 3320b57cec5SDimitry Andric 333*cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr __optional_destruct_base() noexcept : __null_state_(), __engaged_(false) {} 3340b57cec5SDimitry Andric 3350b57cec5SDimitry Andric template <class... _Args> 336*cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr explicit __optional_destruct_base(in_place_t, _Args&&... __args) 337*cb14a3feSDimitry Andric : __val_(std::forward<_Args>(__args)...), __engaged_(true) {} 3380b57cec5SDimitry Andric 33906c3fb27SDimitry Andric# if _LIBCPP_STD_VER >= 23 3400eae32dcSDimitry Andric template <class _Fp, class... _Args> 341*cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr __optional_destruct_base( 342*cb14a3feSDimitry Andric __optional_construct_from_invoke_tag, _Fp&& __f, _Args&&... __args) 3435f757f3fSDimitry Andric : __val_(std::invoke(std::forward<_Fp>(__f), std::forward<_Args>(__args)...)), __engaged_(true) {} 3440eae32dcSDimitry Andric# endif 3450eae32dcSDimitry Andric 346*cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void reset() noexcept { 347*cb14a3feSDimitry Andric if (__engaged_) { 3480b57cec5SDimitry Andric __engaged_ = false; 3490b57cec5SDimitry Andric } 3500b57cec5SDimitry Andric } 3510b57cec5SDimitry Andric}; 3520b57cec5SDimitry Andric 3530b57cec5SDimitry Andrictemplate <class _Tp, bool = is_reference<_Tp>::value> 354*cb14a3feSDimitry Andricstruct __optional_storage_base : __optional_destruct_base<_Tp> { 3550b57cec5SDimitry Andric using __base = __optional_destruct_base<_Tp>; 3560b57cec5SDimitry Andric using value_type = _Tp; 3570b57cec5SDimitry Andric using __base::__base; 3580b57cec5SDimitry Andric 359*cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr bool has_value() const noexcept { return this->__engaged_; } 3600b57cec5SDimitry Andric 361*cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr value_type& __get() & noexcept { return this->__val_; } 362*cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr const value_type& __get() const& noexcept { return this->__val_; } 363*cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr value_type&& __get() && noexcept { return std::move(this->__val_); } 364*cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr const value_type&& __get() const&& noexcept { return std::move(this->__val_); } 3650b57cec5SDimitry Andric 3660b57cec5SDimitry Andric template <class... _Args> 367*cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __construct(_Args&&... __args) { 36806c3fb27SDimitry Andric _LIBCPP_ASSERT_INTERNAL(!has_value(), "__construct called for engaged __optional_storage"); 3695f757f3fSDimitry Andric std::__construct_at(std::addressof(this->__val_), std::forward<_Args>(__args)...); 3700b57cec5SDimitry Andric this->__engaged_ = true; 3710b57cec5SDimitry Andric } 3720b57cec5SDimitry Andric 3730b57cec5SDimitry Andric template <class _That> 374*cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __construct_from(_That&& __opt) { 3750b57cec5SDimitry Andric if (__opt.has_value()) 3765f757f3fSDimitry Andric __construct(std::forward<_That>(__opt).__get()); 3770b57cec5SDimitry Andric } 3780b57cec5SDimitry Andric 3790b57cec5SDimitry Andric template <class _That> 380*cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __assign_from(_That&& __opt) { 381*cb14a3feSDimitry Andric if (this->__engaged_ == __opt.has_value()) { 3820b57cec5SDimitry Andric if (this->__engaged_) 3835f757f3fSDimitry Andric this->__val_ = std::forward<_That>(__opt).__get(); 384*cb14a3feSDimitry Andric } else { 3850b57cec5SDimitry Andric if (this->__engaged_) 3860b57cec5SDimitry Andric this->reset(); 3870b57cec5SDimitry Andric else 3885f757f3fSDimitry Andric __construct(std::forward<_That>(__opt).__get()); 3890b57cec5SDimitry Andric } 3900b57cec5SDimitry Andric } 3910b57cec5SDimitry Andric}; 3920b57cec5SDimitry Andric 39381ad6265SDimitry Andric// optional<T&> is currently required to be ill-formed. However, it may 39481ad6265SDimitry Andric// be allowed in the future. For this reason, it has already been implemented 39581ad6265SDimitry Andric// to ensure we can make the change in an ABI-compatible manner. 3960b57cec5SDimitry Andrictemplate <class _Tp> 397*cb14a3feSDimitry Andricstruct __optional_storage_base<_Tp, true> { 3980b57cec5SDimitry Andric using value_type = _Tp; 3990b57cec5SDimitry Andric using __raw_type = remove_reference_t<_Tp>; 4000b57cec5SDimitry Andric __raw_type* __value_; 4010b57cec5SDimitry Andric 4020b57cec5SDimitry Andric template <class _Up> 40306c3fb27SDimitry Andric static _LIBCPP_HIDE_FROM_ABI constexpr bool __can_bind_reference() { 404bdd1243dSDimitry Andric using _RawUp = __libcpp_remove_reference_t<_Up>; 4050b57cec5SDimitry Andric using _UpPtr = _RawUp*; 406bdd1243dSDimitry Andric using _RawTp = __libcpp_remove_reference_t<_Tp>; 4070b57cec5SDimitry Andric using _TpPtr = _RawTp*; 408*cb14a3feSDimitry Andric using _CheckLValueArg = 409*cb14a3feSDimitry Andric integral_constant<bool, 410*cb14a3feSDimitry Andric (is_lvalue_reference<_Up>::value && is_convertible<_UpPtr, _TpPtr>::value) || 411*cb14a3feSDimitry Andric is_same<_RawUp, reference_wrapper<_RawTp>>::value || 412*cb14a3feSDimitry Andric is_same<_RawUp, reference_wrapper<__remove_const_t<_RawTp>>>::value >; 413*cb14a3feSDimitry Andric return (is_lvalue_reference<_Tp>::value && _CheckLValueArg::value) || 414*cb14a3feSDimitry Andric (is_rvalue_reference<_Tp>::value && !is_lvalue_reference<_Up>::value && 4150b57cec5SDimitry Andric is_convertible<_UpPtr, _TpPtr>::value); 4160b57cec5SDimitry Andric } 4170b57cec5SDimitry Andric 418*cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr __optional_storage_base() noexcept : __value_(nullptr) {} 4190b57cec5SDimitry Andric 4200b57cec5SDimitry Andric template <class _UArg> 421*cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr explicit __optional_storage_base(in_place_t, _UArg&& __uarg) 422*cb14a3feSDimitry Andric : __value_(std::addressof(__uarg)) { 4230b57cec5SDimitry Andric static_assert(__can_bind_reference<_UArg>(), 4240b57cec5SDimitry Andric "Attempted to construct a reference element in tuple from a " 4250b57cec5SDimitry Andric "possible temporary"); 4260b57cec5SDimitry Andric } 4270b57cec5SDimitry Andric 428*cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void reset() noexcept { __value_ = nullptr; } 4290b57cec5SDimitry Andric 430*cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr bool has_value() const noexcept { return __value_ != nullptr; } 4310b57cec5SDimitry Andric 432*cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr value_type& __get() const& noexcept { return *__value_; } 4330b57cec5SDimitry Andric 434*cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr value_type&& __get() const&& noexcept { return std::forward<value_type>(*__value_); } 4350b57cec5SDimitry Andric 4360b57cec5SDimitry Andric template <class _UArg> 437*cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __construct(_UArg&& __val) { 43806c3fb27SDimitry Andric _LIBCPP_ASSERT_INTERNAL(!has_value(), "__construct called for engaged __optional_storage"); 4390b57cec5SDimitry Andric static_assert(__can_bind_reference<_UArg>(), 4400b57cec5SDimitry Andric "Attempted to construct a reference element in tuple from a " 4410b57cec5SDimitry Andric "possible temporary"); 4425f757f3fSDimitry Andric __value_ = std::addressof(__val); 4430b57cec5SDimitry Andric } 4440b57cec5SDimitry Andric 4450b57cec5SDimitry Andric template <class _That> 446*cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __construct_from(_That&& __opt) { 4470b57cec5SDimitry Andric if (__opt.has_value()) 4485f757f3fSDimitry Andric __construct(std::forward<_That>(__opt).__get()); 4490b57cec5SDimitry Andric } 4500b57cec5SDimitry Andric 4510b57cec5SDimitry Andric template <class _That> 452*cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __assign_from(_That&& __opt) { 453*cb14a3feSDimitry Andric if (has_value() == __opt.has_value()) { 4540b57cec5SDimitry Andric if (has_value()) 4555f757f3fSDimitry Andric *__value_ = std::forward<_That>(__opt).__get(); 456*cb14a3feSDimitry Andric } else { 4570b57cec5SDimitry Andric if (has_value()) 4580b57cec5SDimitry Andric reset(); 4590b57cec5SDimitry Andric else 4605f757f3fSDimitry Andric __construct(std::forward<_That>(__opt).__get()); 4610b57cec5SDimitry Andric } 4620b57cec5SDimitry Andric } 4630b57cec5SDimitry Andric}; 4640b57cec5SDimitry Andric 4650b57cec5SDimitry Andrictemplate <class _Tp, bool = is_trivially_copy_constructible<_Tp>::value> 466*cb14a3feSDimitry Andricstruct __optional_copy_base : __optional_storage_base<_Tp> { 4670b57cec5SDimitry Andric using __optional_storage_base<_Tp>::__optional_storage_base; 4680b57cec5SDimitry Andric}; 4690b57cec5SDimitry Andric 4700b57cec5SDimitry Andrictemplate <class _Tp> 471*cb14a3feSDimitry Andricstruct __optional_copy_base<_Tp, false> : __optional_storage_base<_Tp> { 4720b57cec5SDimitry Andric using __optional_storage_base<_Tp>::__optional_storage_base; 4730b57cec5SDimitry Andric 474*cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI __optional_copy_base() = default; 4750b57cec5SDimitry Andric 476*cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 __optional_copy_base(const __optional_copy_base& __opt) { 4770b57cec5SDimitry Andric this->__construct_from(__opt); 4780b57cec5SDimitry Andric } 4790b57cec5SDimitry Andric 480*cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI __optional_copy_base(__optional_copy_base&&) = default; 481*cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI __optional_copy_base& operator=(const __optional_copy_base&) = default; 482*cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI __optional_copy_base& operator=(__optional_copy_base&&) = default; 4830b57cec5SDimitry Andric}; 4840b57cec5SDimitry Andric 4850b57cec5SDimitry Andrictemplate <class _Tp, bool = is_trivially_move_constructible<_Tp>::value> 486*cb14a3feSDimitry Andricstruct __optional_move_base : __optional_copy_base<_Tp> { 4870b57cec5SDimitry Andric using __optional_copy_base<_Tp>::__optional_copy_base; 4880b57cec5SDimitry Andric}; 4890b57cec5SDimitry Andric 4900b57cec5SDimitry Andrictemplate <class _Tp> 491*cb14a3feSDimitry Andricstruct __optional_move_base<_Tp, false> : __optional_copy_base<_Tp> { 4920b57cec5SDimitry Andric using value_type = _Tp; 4930b57cec5SDimitry Andric using __optional_copy_base<_Tp>::__optional_copy_base; 4940b57cec5SDimitry Andric 495*cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI __optional_move_base() = default; 496*cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI __optional_move_base(const __optional_move_base&) = default; 4970b57cec5SDimitry Andric 498*cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 499*cb14a3feSDimitry Andric __optional_move_base(__optional_move_base&& __opt) noexcept(is_nothrow_move_constructible_v<value_type>) { 5005f757f3fSDimitry Andric this->__construct_from(std::move(__opt)); 5010b57cec5SDimitry Andric } 5020b57cec5SDimitry Andric 503*cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI __optional_move_base& operator=(const __optional_move_base&) = default; 504*cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI __optional_move_base& operator=(__optional_move_base&&) = default; 5050b57cec5SDimitry Andric}; 5060b57cec5SDimitry Andric 507*cb14a3feSDimitry Andrictemplate <class _Tp, 508*cb14a3feSDimitry Andric bool = is_trivially_destructible<_Tp>::value && is_trivially_copy_constructible<_Tp>::value && 5090b57cec5SDimitry Andric is_trivially_copy_assignable<_Tp>::value> 510*cb14a3feSDimitry Andricstruct __optional_copy_assign_base : __optional_move_base<_Tp> { 5110b57cec5SDimitry Andric using __optional_move_base<_Tp>::__optional_move_base; 5120b57cec5SDimitry Andric}; 5130b57cec5SDimitry Andric 5140b57cec5SDimitry Andrictemplate <class _Tp> 515*cb14a3feSDimitry Andricstruct __optional_copy_assign_base<_Tp, false> : __optional_move_base<_Tp> { 5160b57cec5SDimitry Andric using __optional_move_base<_Tp>::__optional_move_base; 5170b57cec5SDimitry Andric 518*cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI __optional_copy_assign_base() = default; 519*cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI __optional_copy_assign_base(const __optional_copy_assign_base&) = default; 520*cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI __optional_copy_assign_base(__optional_copy_assign_base&&) = default; 5210b57cec5SDimitry Andric 522*cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 __optional_copy_assign_base& 523*cb14a3feSDimitry Andric operator=(const __optional_copy_assign_base& __opt) { 5240b57cec5SDimitry Andric this->__assign_from(__opt); 5250b57cec5SDimitry Andric return *this; 5260b57cec5SDimitry Andric } 5270b57cec5SDimitry Andric 528*cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI __optional_copy_assign_base& operator=(__optional_copy_assign_base&&) = default; 5290b57cec5SDimitry Andric}; 5300b57cec5SDimitry Andric 531*cb14a3feSDimitry Andrictemplate <class _Tp, 532*cb14a3feSDimitry Andric bool = is_trivially_destructible<_Tp>::value && is_trivially_move_constructible<_Tp>::value && 5330b57cec5SDimitry Andric is_trivially_move_assignable<_Tp>::value> 534*cb14a3feSDimitry Andricstruct __optional_move_assign_base : __optional_copy_assign_base<_Tp> { 5350b57cec5SDimitry Andric using __optional_copy_assign_base<_Tp>::__optional_copy_assign_base; 5360b57cec5SDimitry Andric}; 5370b57cec5SDimitry Andric 5380b57cec5SDimitry Andrictemplate <class _Tp> 539*cb14a3feSDimitry Andricstruct __optional_move_assign_base<_Tp, false> : __optional_copy_assign_base<_Tp> { 5400b57cec5SDimitry Andric using value_type = _Tp; 5410b57cec5SDimitry Andric using __optional_copy_assign_base<_Tp>::__optional_copy_assign_base; 5420b57cec5SDimitry Andric 543*cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI __optional_move_assign_base() = default; 544*cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI __optional_move_assign_base(const __optional_move_assign_base& __opt) = default; 545*cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI __optional_move_assign_base(__optional_move_assign_base&&) = default; 546*cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI __optional_move_assign_base& operator=(const __optional_move_assign_base&) = default; 5470b57cec5SDimitry Andric 548*cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 __optional_move_assign_base& 549*cb14a3feSDimitry Andric operator=(__optional_move_assign_base&& __opt) noexcept( 550*cb14a3feSDimitry Andric is_nothrow_move_assignable_v<value_type> && is_nothrow_move_constructible_v<value_type>) { 5515f757f3fSDimitry Andric this->__assign_from(std::move(__opt)); 5520b57cec5SDimitry Andric return *this; 5530b57cec5SDimitry Andric } 5540b57cec5SDimitry Andric}; 5550b57cec5SDimitry Andric 5560b57cec5SDimitry Andrictemplate <class _Tp> 557*cb14a3feSDimitry Andricusing __optional_sfinae_ctor_base_t = 558*cb14a3feSDimitry Andric __sfinae_ctor_base< is_copy_constructible<_Tp>::value, is_move_constructible<_Tp>::value >; 5590b57cec5SDimitry Andric 5600b57cec5SDimitry Andrictemplate <class _Tp> 561*cb14a3feSDimitry Andricusing __optional_sfinae_assign_base_t = 562*cb14a3feSDimitry Andric __sfinae_assign_base< (is_copy_constructible<_Tp>::value && is_copy_assignable<_Tp>::value), 563*cb14a3feSDimitry Andric (is_move_constructible<_Tp>::value && is_move_assignable<_Tp>::value) >; 5640b57cec5SDimitry Andric 5650b57cec5SDimitry Andrictemplate <class _Tp> 5660eae32dcSDimitry Andricclass optional; 56706c3fb27SDimitry Andric 56806c3fb27SDimitry Andric# if _LIBCPP_STD_VER >= 20 56906c3fb27SDimitry Andric 57006c3fb27SDimitry Andrictemplate <class _Tp> 57106c3fb27SDimitry Andricconcept __is_derived_from_optional = requires(const _Tp& __t) { []<class _Up>(const optional<_Up>&) {}(__t); }; 57206c3fb27SDimitry Andric 57306c3fb27SDimitry Andric# endif // _LIBCPP_STD_VER >= 20 57406c3fb27SDimitry Andric 5750eae32dcSDimitry Andrictemplate <class _Tp> 5760eae32dcSDimitry Andricstruct __is_std_optional : false_type {}; 577*cb14a3feSDimitry Andrictemplate <class _Tp> 578*cb14a3feSDimitry Andricstruct __is_std_optional<optional<_Tp>> : true_type {}; 5790eae32dcSDimitry Andric 5800eae32dcSDimitry Andrictemplate <class _Tp> 58106c3fb27SDimitry Andricclass _LIBCPP_DECLSPEC_EMPTY_BASES optional 582*cb14a3feSDimitry Andric : private __optional_move_assign_base<_Tp>, 583*cb14a3feSDimitry Andric private __optional_sfinae_ctor_base_t<_Tp>, 584*cb14a3feSDimitry Andric private __optional_sfinae_assign_base_t<_Tp> { 5850b57cec5SDimitry Andric using __base = __optional_move_assign_base<_Tp>; 586*cb14a3feSDimitry Andric 5870b57cec5SDimitry Andricpublic: 5880b57cec5SDimitry Andric using value_type = _Tp; 5890b57cec5SDimitry Andric 5900b57cec5SDimitry Andricprivate: 5910b57cec5SDimitry Andric // Disable the reference extension using this static assert. 592bdd1243dSDimitry Andric static_assert(!is_same_v<__remove_cvref_t<value_type>, in_place_t>, 5930b57cec5SDimitry Andric "instantiation of optional with in_place_t is ill-formed"); 594bdd1243dSDimitry Andric static_assert(!is_same_v<__remove_cvref_t<value_type>, nullopt_t>, 5950b57cec5SDimitry Andric "instantiation of optional with nullopt_t is ill-formed"); 596*cb14a3feSDimitry Andric static_assert(!is_reference_v<value_type>, "instantiation of optional with a reference type is ill-formed"); 597*cb14a3feSDimitry Andric static_assert(is_destructible_v<value_type>, "instantiation of optional with a non-destructible type is ill-formed"); 598*cb14a3feSDimitry Andric static_assert(!is_array_v<value_type>, "instantiation of optional with an array type is ill-formed"); 5990b57cec5SDimitry Andric 6000b57cec5SDimitry Andric // LWG2756: conditionally explicit conversion from _Up 6010b57cec5SDimitry Andric struct _CheckOptionalArgsConstructor { 6020b57cec5SDimitry Andric template <class _Up> 60306c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI static constexpr bool __enable_implicit() { 604*cb14a3feSDimitry Andric return is_constructible_v<_Tp, _Up&&> && is_convertible_v<_Up&&, _Tp>; 6050b57cec5SDimitry Andric } 6060b57cec5SDimitry Andric 6070b57cec5SDimitry Andric template <class _Up> 60806c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI static constexpr bool __enable_explicit() { 609*cb14a3feSDimitry Andric return is_constructible_v<_Tp, _Up&&> && !is_convertible_v<_Up&&, _Tp>; 6100b57cec5SDimitry Andric } 6110b57cec5SDimitry Andric }; 6120b57cec5SDimitry Andric template <class _Up> 613*cb14a3feSDimitry Andric using _CheckOptionalArgsCtor = 614*cb14a3feSDimitry Andric _If< _IsNotSame<__remove_cvref_t<_Up>, in_place_t>::value && _IsNotSame<__remove_cvref_t<_Up>, optional>::value && 6155f757f3fSDimitry Andric (!is_same_v<remove_cv_t<_Tp>, bool> || !__is_std_optional<__remove_cvref_t<_Up>>::value), 6160b57cec5SDimitry Andric _CheckOptionalArgsConstructor, 617*cb14a3feSDimitry Andric __check_tuple_constructor_fail >; 6180b57cec5SDimitry Andric template <class _QualUp> 6190b57cec5SDimitry Andric struct _CheckOptionalLikeConstructor { 6200b57cec5SDimitry Andric template <class _Up, class _Opt = optional<_Up>> 621*cb14a3feSDimitry Andric using __check_constructible_from_opt = 622*cb14a3feSDimitry Andric _Or< is_constructible<_Tp, _Opt&>, 6230b57cec5SDimitry Andric is_constructible<_Tp, _Opt const&>, 6240b57cec5SDimitry Andric is_constructible<_Tp, _Opt&&>, 6250b57cec5SDimitry Andric is_constructible<_Tp, _Opt const&&>, 6260b57cec5SDimitry Andric is_convertible<_Opt&, _Tp>, 6270b57cec5SDimitry Andric is_convertible<_Opt const&, _Tp>, 6280b57cec5SDimitry Andric is_convertible<_Opt&&, _Tp>, 629*cb14a3feSDimitry Andric is_convertible<_Opt const&&, _Tp> >; 6300b57cec5SDimitry Andric template <class _Up, class _Opt = optional<_Up>> 631*cb14a3feSDimitry Andric using __check_assignable_from_opt = 632*cb14a3feSDimitry Andric _Or< is_assignable<_Tp&, _Opt&>, 6330b57cec5SDimitry Andric is_assignable<_Tp&, _Opt const&>, 6340b57cec5SDimitry Andric is_assignable<_Tp&, _Opt&&>, 635*cb14a3feSDimitry Andric is_assignable<_Tp&, _Opt const&&> >; 6360b57cec5SDimitry Andric template <class _Up, class _QUp = _QualUp> 63706c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI static constexpr bool __enable_implicit() { 6380b57cec5SDimitry Andric return is_convertible<_QUp, _Tp>::value && 6395f757f3fSDimitry Andric (is_same_v<remove_cv_t<_Tp>, bool> || !__check_constructible_from_opt<_Up>::value); 6400b57cec5SDimitry Andric } 6410b57cec5SDimitry Andric template <class _Up, class _QUp = _QualUp> 64206c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI static constexpr bool __enable_explicit() { 6430b57cec5SDimitry Andric return !is_convertible<_QUp, _Tp>::value && 6445f757f3fSDimitry Andric (is_same_v<remove_cv_t<_Tp>, bool> || !__check_constructible_from_opt<_Up>::value); 6450b57cec5SDimitry Andric } 6460b57cec5SDimitry Andric template <class _Up, class _QUp = _QualUp> 64706c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI static constexpr bool __enable_assign() { 648e8d8bef9SDimitry Andric // Construction and assignability of _QUp to _Tp has already been 6490b57cec5SDimitry Andric // checked. 650*cb14a3feSDimitry Andric return !__check_constructible_from_opt<_Up>::value && !__check_assignable_from_opt<_Up>::value; 6510b57cec5SDimitry Andric } 6520b57cec5SDimitry Andric }; 6530b57cec5SDimitry Andric 6540b57cec5SDimitry Andric template <class _Up, class _QualUp> 655*cb14a3feSDimitry Andric using _CheckOptionalLikeCtor = 656*cb14a3feSDimitry Andric _If< _And< _IsNotSame<_Up, _Tp>, is_constructible<_Tp, _QualUp> >::value, 6570b57cec5SDimitry Andric _CheckOptionalLikeConstructor<_QualUp>, 658*cb14a3feSDimitry Andric __check_tuple_constructor_fail >; 6590b57cec5SDimitry Andric template <class _Up, class _QualUp> 660*cb14a3feSDimitry Andric using _CheckOptionalLikeAssign = 661*cb14a3feSDimitry Andric _If< _And< _IsNotSame<_Up, _Tp>, is_constructible<_Tp, _QualUp>, is_assignable<_Tp&, _QualUp> >::value, 6620b57cec5SDimitry Andric _CheckOptionalLikeConstructor<_QualUp>, 663*cb14a3feSDimitry Andric __check_tuple_constructor_fail >; 6640eae32dcSDimitry Andric 6650b57cec5SDimitry Andricpublic: 6665f757f3fSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr optional() noexcept {} 6675f757f3fSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr optional(const optional&) = default; 6685f757f3fSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr optional(optional&&) = default; 6695f757f3fSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr optional(nullopt_t) noexcept {} 6700b57cec5SDimitry Andric 671*cb14a3feSDimitry Andric template < 672*cb14a3feSDimitry Andric class _InPlaceT, 673*cb14a3feSDimitry Andric class... _Args, 674*cb14a3feSDimitry Andric class = enable_if_t< _And< _IsSame<_InPlaceT, in_place_t>, is_constructible<value_type, _Args...> >::value > > 675*cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr explicit optional(_InPlaceT, _Args&&... __args) 6765f757f3fSDimitry Andric : __base(in_place, std::forward<_Args>(__args)...) {} 6770b57cec5SDimitry Andric 678*cb14a3feSDimitry Andric template <class _Up, 679*cb14a3feSDimitry Andric class... _Args, 680*cb14a3feSDimitry Andric class = enable_if_t< is_constructible_v<value_type, initializer_list<_Up>&, _Args...>> > 681*cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr explicit optional(in_place_t, initializer_list<_Up> __il, _Args&&... __args) 6825f757f3fSDimitry Andric : __base(in_place, __il, std::forward<_Args>(__args)...) {} 6830b57cec5SDimitry Andric 684*cb14a3feSDimitry Andric template <class _Up = value_type, 685*cb14a3feSDimitry Andric enable_if_t< _CheckOptionalArgsCtor<_Up>::template __enable_implicit<_Up>(), int> = 0> 686*cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr optional(_Up&& __v) : __base(in_place, std::forward<_Up>(__v)) {} 6870b57cec5SDimitry Andric 688*cb14a3feSDimitry Andric template <class _Up, enable_if_t< _CheckOptionalArgsCtor<_Up>::template __enable_explicit<_Up>(), int> = 0> 689*cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr explicit optional(_Up&& __v) : __base(in_place, std::forward<_Up>(__v)) {} 6900b57cec5SDimitry Andric 6910b57cec5SDimitry Andric // LWG2756: conditionally explicit conversion from const optional<_Up>& 692*cb14a3feSDimitry Andric template <class _Up, 693*cb14a3feSDimitry Andric enable_if_t< _CheckOptionalLikeCtor<_Up, _Up const&>::template __enable_implicit<_Up>(), int> = 0> 694*cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 optional(const optional<_Up>& __v) { 6950b57cec5SDimitry Andric this->__construct_from(__v); 6960b57cec5SDimitry Andric } 697*cb14a3feSDimitry Andric template <class _Up, 698*cb14a3feSDimitry Andric enable_if_t< _CheckOptionalLikeCtor<_Up, _Up const&>::template __enable_explicit<_Up>(), int> = 0> 699*cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 explicit optional(const optional<_Up>& __v) { 7000b57cec5SDimitry Andric this->__construct_from(__v); 7010b57cec5SDimitry Andric } 7020b57cec5SDimitry Andric 7030b57cec5SDimitry Andric // LWG2756: conditionally explicit conversion from optional<_Up>&& 704*cb14a3feSDimitry Andric template <class _Up, enable_if_t< _CheckOptionalLikeCtor<_Up, _Up&&>::template __enable_implicit<_Up>(), int> = 0> 705*cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 optional(optional<_Up>&& __v) { 7065f757f3fSDimitry Andric this->__construct_from(std::move(__v)); 7070b57cec5SDimitry Andric } 708*cb14a3feSDimitry Andric template <class _Up, enable_if_t< _CheckOptionalLikeCtor<_Up, _Up&&>::template __enable_explicit<_Up>(), int> = 0> 709*cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 explicit optional(optional<_Up>&& __v) { 7105f757f3fSDimitry Andric this->__construct_from(std::move(__v)); 7110b57cec5SDimitry Andric } 7120b57cec5SDimitry Andric 71306c3fb27SDimitry Andric# if _LIBCPP_STD_VER >= 23 7140eae32dcSDimitry Andric template <class _Fp, class... _Args> 715*cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr explicit optional(__optional_construct_from_invoke_tag, _Fp&& __f, _Args&&... __args) 716*cb14a3feSDimitry Andric : __base(__optional_construct_from_invoke_tag{}, std::forward<_Fp>(__f), std::forward<_Args>(__args)...) {} 7170eae32dcSDimitry Andric# endif 7180eae32dcSDimitry Andric 719*cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 optional& operator=(nullopt_t) noexcept { 7200b57cec5SDimitry Andric reset(); 7210b57cec5SDimitry Andric return *this; 7220b57cec5SDimitry Andric } 7230b57cec5SDimitry Andric 72406c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr optional& operator=(const optional&) = default; 72506c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr optional& operator=(optional&&) = default; 7260b57cec5SDimitry Andric 7270b57cec5SDimitry Andric // LWG2756 728*cb14a3feSDimitry Andric template < 729*cb14a3feSDimitry Andric class _Up = value_type, 730*cb14a3feSDimitry Andric class = enable_if_t< _And< _IsNotSame<__remove_cvref_t<_Up>, optional>, 731*cb14a3feSDimitry Andric _Or< _IsNotSame<__remove_cvref_t<_Up>, value_type>, _Not<is_scalar<value_type>> >, 7320b57cec5SDimitry Andric is_constructible<value_type, _Up>, 733*cb14a3feSDimitry Andric is_assignable<value_type&, _Up> >::value> > 734*cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 optional& operator=(_Up&& __v) { 7350b57cec5SDimitry Andric if (this->has_value()) 7365f757f3fSDimitry Andric this->__get() = std::forward<_Up>(__v); 7370b57cec5SDimitry Andric else 7385f757f3fSDimitry Andric this->__construct(std::forward<_Up>(__v)); 7390b57cec5SDimitry Andric return *this; 7400b57cec5SDimitry Andric } 7410b57cec5SDimitry Andric 7420b57cec5SDimitry Andric // LWG2756 743*cb14a3feSDimitry Andric template <class _Up, 744*cb14a3feSDimitry Andric enable_if_t< _CheckOptionalLikeAssign<_Up, _Up const&>::template __enable_assign<_Up>(), int> = 0> 745*cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 optional& operator=(const optional<_Up>& __v) { 7460b57cec5SDimitry Andric this->__assign_from(__v); 7470b57cec5SDimitry Andric return *this; 7480b57cec5SDimitry Andric } 7490b57cec5SDimitry Andric 7500b57cec5SDimitry Andric // LWG2756 751*cb14a3feSDimitry Andric template <class _Up, enable_if_t< _CheckOptionalLikeCtor<_Up, _Up&&>::template __enable_assign<_Up>(), int> = 0> 752*cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 optional& operator=(optional<_Up>&& __v) { 7535f757f3fSDimitry Andric this->__assign_from(std::move(__v)); 7540b57cec5SDimitry Andric return *this; 7550b57cec5SDimitry Andric } 7560b57cec5SDimitry Andric 757*cb14a3feSDimitry Andric template <class... _Args, class = enable_if_t< is_constructible_v<value_type, _Args...> > > 758*cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _Tp& emplace(_Args&&... __args) { 7590b57cec5SDimitry Andric reset(); 7605f757f3fSDimitry Andric this->__construct(std::forward<_Args>(__args)...); 7610b57cec5SDimitry Andric return this->__get(); 7620b57cec5SDimitry Andric } 7630b57cec5SDimitry Andric 764*cb14a3feSDimitry Andric template <class _Up, 765*cb14a3feSDimitry Andric class... _Args, 766*cb14a3feSDimitry Andric class = enable_if_t< is_constructible_v<value_type, initializer_list<_Up>&, _Args...> > > 767*cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _Tp& emplace(initializer_list<_Up> __il, _Args&&... __args) { 7680b57cec5SDimitry Andric reset(); 7695f757f3fSDimitry Andric this->__construct(__il, std::forward<_Args>(__args)...); 7700b57cec5SDimitry Andric return this->__get(); 7710b57cec5SDimitry Andric } 7720b57cec5SDimitry Andric 773*cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void 774*cb14a3feSDimitry Andric swap(optional& __opt) noexcept(is_nothrow_move_constructible_v<value_type> && is_nothrow_swappable_v<value_type>) { 775*cb14a3feSDimitry Andric if (this->has_value() == __opt.has_value()) { 7765f757f3fSDimitry Andric using std::swap; 7770b57cec5SDimitry Andric if (this->has_value()) 7780b57cec5SDimitry Andric swap(this->__get(), __opt.__get()); 779*cb14a3feSDimitry Andric } else { 780*cb14a3feSDimitry Andric if (this->has_value()) { 7815f757f3fSDimitry Andric __opt.__construct(std::move(this->__get())); 7820b57cec5SDimitry Andric reset(); 783*cb14a3feSDimitry Andric } else { 7845f757f3fSDimitry Andric this->__construct(std::move(__opt.__get())); 7850b57cec5SDimitry Andric __opt.reset(); 7860b57cec5SDimitry Andric } 7870b57cec5SDimitry Andric } 7880b57cec5SDimitry Andric } 7890b57cec5SDimitry Andric 790*cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr add_pointer_t<value_type const> operator->() const { 79106c3fb27SDimitry Andric _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(this->has_value(), "optional operator-> called on a disengaged value"); 7925f757f3fSDimitry Andric return std::addressof(this->__get()); 7930b57cec5SDimitry Andric } 7940b57cec5SDimitry Andric 795*cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr add_pointer_t<value_type> operator->() { 79606c3fb27SDimitry Andric _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(this->has_value(), "optional operator-> called on a disengaged value"); 7975f757f3fSDimitry Andric return std::addressof(this->__get()); 7980b57cec5SDimitry Andric } 7990b57cec5SDimitry Andric 800*cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr const value_type& operator*() const& noexcept { 80106c3fb27SDimitry Andric _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(this->has_value(), "optional operator* called on a disengaged value"); 8020b57cec5SDimitry Andric return this->__get(); 8030b57cec5SDimitry Andric } 8040b57cec5SDimitry Andric 805*cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr value_type& operator*() & noexcept { 80606c3fb27SDimitry Andric _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(this->has_value(), "optional operator* called on a disengaged value"); 8070b57cec5SDimitry Andric return this->__get(); 8080b57cec5SDimitry Andric } 8090b57cec5SDimitry Andric 810*cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr value_type&& operator*() && noexcept { 81106c3fb27SDimitry Andric _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(this->has_value(), "optional operator* called on a disengaged value"); 8125f757f3fSDimitry Andric return std::move(this->__get()); 8130b57cec5SDimitry Andric } 8140b57cec5SDimitry Andric 815*cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr const value_type&& operator*() const&& noexcept { 81606c3fb27SDimitry Andric _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(this->has_value(), "optional operator* called on a disengaged value"); 8175f757f3fSDimitry Andric return std::move(this->__get()); 8180b57cec5SDimitry Andric } 8190b57cec5SDimitry Andric 820*cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr explicit operator bool() const noexcept { return has_value(); } 8210b57cec5SDimitry Andric 8220b57cec5SDimitry Andric using __base::__get; 823*cb14a3feSDimitry Andric using __base::has_value; 8240b57cec5SDimitry Andric 825*cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS constexpr value_type const& value() const& { 8260b57cec5SDimitry Andric if (!this->has_value()) 8270b57cec5SDimitry Andric __throw_bad_optional_access(); 8280b57cec5SDimitry Andric return this->__get(); 8290b57cec5SDimitry Andric } 8300b57cec5SDimitry Andric 831*cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS constexpr value_type& value() & { 8320b57cec5SDimitry Andric if (!this->has_value()) 8330b57cec5SDimitry Andric __throw_bad_optional_access(); 8340b57cec5SDimitry Andric return this->__get(); 8350b57cec5SDimitry Andric } 8360b57cec5SDimitry Andric 837*cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS constexpr value_type&& value() && { 8380b57cec5SDimitry Andric if (!this->has_value()) 8390b57cec5SDimitry Andric __throw_bad_optional_access(); 8405f757f3fSDimitry Andric return std::move(this->__get()); 8410b57cec5SDimitry Andric } 8420b57cec5SDimitry Andric 843*cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS constexpr value_type const&& value() const&& { 8440b57cec5SDimitry Andric if (!this->has_value()) 8450b57cec5SDimitry Andric __throw_bad_optional_access(); 8465f757f3fSDimitry Andric return std::move(this->__get()); 8470b57cec5SDimitry Andric } 8480b57cec5SDimitry Andric 8490b57cec5SDimitry Andric template <class _Up> 850*cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr value_type value_or(_Up&& __v) const& { 851*cb14a3feSDimitry Andric static_assert(is_copy_constructible_v<value_type>, "optional<T>::value_or: T must be copy constructible"); 852*cb14a3feSDimitry Andric static_assert(is_convertible_v<_Up, value_type>, "optional<T>::value_or: U must be convertible to T"); 853*cb14a3feSDimitry Andric return this->has_value() ? this->__get() : static_cast<value_type>(std::forward<_Up>(__v)); 8540b57cec5SDimitry Andric } 8550b57cec5SDimitry Andric 8560b57cec5SDimitry Andric template <class _Up> 857*cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr value_type value_or(_Up&& __v) && { 858*cb14a3feSDimitry Andric static_assert(is_move_constructible_v<value_type>, "optional<T>::value_or: T must be move constructible"); 859*cb14a3feSDimitry Andric static_assert(is_convertible_v<_Up, value_type>, "optional<T>::value_or: U must be convertible to T"); 860*cb14a3feSDimitry Andric return this->has_value() ? std::move(this->__get()) : static_cast<value_type>(std::forward<_Up>(__v)); 8610b57cec5SDimitry Andric } 8620b57cec5SDimitry Andric 86306c3fb27SDimitry Andric# if _LIBCPP_STD_VER >= 23 8640eae32dcSDimitry Andric template <class _Func> 865*cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS constexpr auto and_then(_Func&& __f) & { 8660eae32dcSDimitry Andric using _Up = invoke_result_t<_Func, value_type&>; 8670eae32dcSDimitry Andric static_assert(__is_std_optional<remove_cvref_t<_Up>>::value, 8680eae32dcSDimitry Andric "Result of f(value()) must be a specialization of std::optional"); 8690eae32dcSDimitry Andric if (*this) 8705f757f3fSDimitry Andric return std::invoke(std::forward<_Func>(__f), value()); 8710eae32dcSDimitry Andric return remove_cvref_t<_Up>(); 8720eae32dcSDimitry Andric } 8730eae32dcSDimitry Andric 8740eae32dcSDimitry Andric template <class _Func> 875*cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS constexpr auto and_then(_Func&& __f) const& { 8760eae32dcSDimitry Andric using _Up = invoke_result_t<_Func, const value_type&>; 8770eae32dcSDimitry Andric static_assert(__is_std_optional<remove_cvref_t<_Up>>::value, 8780eae32dcSDimitry Andric "Result of f(value()) must be a specialization of std::optional"); 8790eae32dcSDimitry Andric if (*this) 8805f757f3fSDimitry Andric return std::invoke(std::forward<_Func>(__f), value()); 8810eae32dcSDimitry Andric return remove_cvref_t<_Up>(); 8820eae32dcSDimitry Andric } 8830eae32dcSDimitry Andric 8840eae32dcSDimitry Andric template <class _Func> 885*cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS constexpr auto and_then(_Func&& __f) && { 8860eae32dcSDimitry Andric using _Up = invoke_result_t<_Func, value_type&&>; 8870eae32dcSDimitry Andric static_assert(__is_std_optional<remove_cvref_t<_Up>>::value, 8880eae32dcSDimitry Andric "Result of f(std::move(value())) must be a specialization of std::optional"); 8890eae32dcSDimitry Andric if (*this) 8905f757f3fSDimitry Andric return std::invoke(std::forward<_Func>(__f), std::move(value())); 8910eae32dcSDimitry Andric return remove_cvref_t<_Up>(); 8920eae32dcSDimitry Andric } 8930eae32dcSDimitry Andric 8940eae32dcSDimitry Andric template <class _Func> 895*cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr auto and_then(_Func&& __f) const&& { 8960eae32dcSDimitry Andric using _Up = invoke_result_t<_Func, const value_type&&>; 8970eae32dcSDimitry Andric static_assert(__is_std_optional<remove_cvref_t<_Up>>::value, 8980eae32dcSDimitry Andric "Result of f(std::move(value())) must be a specialization of std::optional"); 8990eae32dcSDimitry Andric if (*this) 9005f757f3fSDimitry Andric return std::invoke(std::forward<_Func>(__f), std::move(value())); 9010eae32dcSDimitry Andric return remove_cvref_t<_Up>(); 9020eae32dcSDimitry Andric } 9030eae32dcSDimitry Andric 9040eae32dcSDimitry Andric template <class _Func> 905*cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS constexpr auto transform(_Func&& __f) & { 9060eae32dcSDimitry Andric using _Up = remove_cv_t<invoke_result_t<_Func, value_type&>>; 9070eae32dcSDimitry Andric static_assert(!is_array_v<_Up>, "Result of f(value()) should not be an Array"); 908*cb14a3feSDimitry Andric static_assert(!is_same_v<_Up, in_place_t>, "Result of f(value()) should not be std::in_place_t"); 909*cb14a3feSDimitry Andric static_assert(!is_same_v<_Up, nullopt_t>, "Result of f(value()) should not be std::nullopt_t"); 9100eae32dcSDimitry Andric static_assert(is_object_v<_Up>, "Result of f(value()) should be an object type"); 9110eae32dcSDimitry Andric if (*this) 9125f757f3fSDimitry Andric return optional<_Up>(__optional_construct_from_invoke_tag{}, std::forward<_Func>(__f), value()); 9130eae32dcSDimitry Andric return optional<_Up>(); 9140eae32dcSDimitry Andric } 9150eae32dcSDimitry Andric 9160eae32dcSDimitry Andric template <class _Func> 917*cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS constexpr auto transform(_Func&& __f) const& { 9180eae32dcSDimitry Andric using _Up = remove_cv_t<invoke_result_t<_Func, const value_type&>>; 9190eae32dcSDimitry Andric static_assert(!is_array_v<_Up>, "Result of f(value()) should not be an Array"); 920*cb14a3feSDimitry Andric static_assert(!is_same_v<_Up, in_place_t>, "Result of f(value()) should not be std::in_place_t"); 921*cb14a3feSDimitry Andric static_assert(!is_same_v<_Up, nullopt_t>, "Result of f(value()) should not be std::nullopt_t"); 9220eae32dcSDimitry Andric static_assert(is_object_v<_Up>, "Result of f(value()) should be an object type"); 9230eae32dcSDimitry Andric if (*this) 9245f757f3fSDimitry Andric return optional<_Up>(__optional_construct_from_invoke_tag{}, std::forward<_Func>(__f), value()); 9250eae32dcSDimitry Andric return optional<_Up>(); 9260eae32dcSDimitry Andric } 9270eae32dcSDimitry Andric 9280eae32dcSDimitry Andric template <class _Func> 929*cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS constexpr auto transform(_Func&& __f) && { 9300eae32dcSDimitry Andric using _Up = remove_cv_t<invoke_result_t<_Func, value_type&&>>; 9310eae32dcSDimitry Andric static_assert(!is_array_v<_Up>, "Result of f(std::move(value())) should not be an Array"); 932*cb14a3feSDimitry Andric static_assert(!is_same_v<_Up, in_place_t>, "Result of f(std::move(value())) should not be std::in_place_t"); 933*cb14a3feSDimitry Andric static_assert(!is_same_v<_Up, nullopt_t>, "Result of f(std::move(value())) should not be std::nullopt_t"); 9340eae32dcSDimitry Andric static_assert(is_object_v<_Up>, "Result of f(std::move(value())) should be an object type"); 9350eae32dcSDimitry Andric if (*this) 9365f757f3fSDimitry Andric return optional<_Up>(__optional_construct_from_invoke_tag{}, std::forward<_Func>(__f), std::move(value())); 9370eae32dcSDimitry Andric return optional<_Up>(); 9380eae32dcSDimitry Andric } 9390eae32dcSDimitry Andric 9400eae32dcSDimitry Andric template <class _Func> 941*cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS constexpr auto transform(_Func&& __f) const&& { 9420eae32dcSDimitry Andric using _Up = remove_cvref_t<invoke_result_t<_Func, const value_type&&>>; 9430eae32dcSDimitry Andric static_assert(!is_array_v<_Up>, "Result of f(std::move(value())) should not be an Array"); 944*cb14a3feSDimitry Andric static_assert(!is_same_v<_Up, in_place_t>, "Result of f(std::move(value())) should not be std::in_place_t"); 945*cb14a3feSDimitry Andric static_assert(!is_same_v<_Up, nullopt_t>, "Result of f(std::move(value())) should not be std::nullopt_t"); 9460eae32dcSDimitry Andric static_assert(is_object_v<_Up>, "Result of f(std::move(value())) should be an object type"); 9470eae32dcSDimitry Andric if (*this) 9485f757f3fSDimitry Andric return optional<_Up>(__optional_construct_from_invoke_tag{}, std::forward<_Func>(__f), std::move(value())); 9490eae32dcSDimitry Andric return optional<_Up>(); 9500eae32dcSDimitry Andric } 9510eae32dcSDimitry Andric 9520eae32dcSDimitry Andric template <invocable _Func> 953*cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr optional or_else(_Func&& __f) const& 954*cb14a3feSDimitry Andric requires is_copy_constructible_v<value_type> 955*cb14a3feSDimitry Andric { 9560eae32dcSDimitry Andric static_assert(is_same_v<remove_cvref_t<invoke_result_t<_Func>>, optional>, 9570eae32dcSDimitry Andric "Result of f() should be the same type as this optional"); 9580eae32dcSDimitry Andric if (*this) 9590eae32dcSDimitry Andric return *this; 9605f757f3fSDimitry Andric return std::forward<_Func>(__f)(); 9610eae32dcSDimitry Andric } 9620eae32dcSDimitry Andric 9630eae32dcSDimitry Andric template <invocable _Func> 964*cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr optional or_else(_Func&& __f) && 965*cb14a3feSDimitry Andric requires is_move_constructible_v<value_type> 966*cb14a3feSDimitry Andric { 9670eae32dcSDimitry Andric static_assert(is_same_v<remove_cvref_t<invoke_result_t<_Func>>, optional>, 9680eae32dcSDimitry Andric "Result of f() should be the same type as this optional"); 9690eae32dcSDimitry Andric if (*this) 9705f757f3fSDimitry Andric return std::move(*this); 9715f757f3fSDimitry Andric return std::forward<_Func>(__f)(); 9720eae32dcSDimitry Andric } 97306c3fb27SDimitry Andric# endif // _LIBCPP_STD_VER >= 23 9740eae32dcSDimitry Andric 9750b57cec5SDimitry Andric using __base::reset; 9760b57cec5SDimitry Andric}; 9770b57cec5SDimitry Andric 978349cc55cSDimitry Andric# if _LIBCPP_STD_VER >= 17 97904eeddc0SDimitry Andrictemplate <class _Tp> 98004eeddc0SDimitry Andricoptional(_Tp) -> optional<_Tp>; 9810b57cec5SDimitry Andric# endif 9820b57cec5SDimitry Andric 9830b57cec5SDimitry Andric// Comparisons between optionals 9840b57cec5SDimitry Andrictemplate <class _Tp, class _Up> 985*cb14a3feSDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr enable_if_t< 986*cb14a3feSDimitry Andric is_convertible_v<decltype(std::declval<const _Tp&>() == std::declval<const _Up&>()), bool>, 987*cb14a3feSDimitry Andric bool > 988*cb14a3feSDimitry Andricoperator==(const optional<_Tp>& __x, const optional<_Up>& __y) { 9890b57cec5SDimitry Andric if (static_cast<bool>(__x) != static_cast<bool>(__y)) 9900b57cec5SDimitry Andric return false; 9910b57cec5SDimitry Andric if (!static_cast<bool>(__x)) 9920b57cec5SDimitry Andric return true; 9930b57cec5SDimitry Andric return *__x == *__y; 9940b57cec5SDimitry Andric} 9950b57cec5SDimitry Andric 9960b57cec5SDimitry Andrictemplate <class _Tp, class _Up> 997*cb14a3feSDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr enable_if_t< 998*cb14a3feSDimitry Andric is_convertible_v<decltype(std::declval<const _Tp&>() != std::declval<const _Up&>()), bool>, 999*cb14a3feSDimitry Andric bool > 1000*cb14a3feSDimitry Andricoperator!=(const optional<_Tp>& __x, const optional<_Up>& __y) { 10010b57cec5SDimitry Andric if (static_cast<bool>(__x) != static_cast<bool>(__y)) 10020b57cec5SDimitry Andric return true; 10030b57cec5SDimitry Andric if (!static_cast<bool>(__x)) 10040b57cec5SDimitry Andric return false; 10050b57cec5SDimitry Andric return *__x != *__y; 10060b57cec5SDimitry Andric} 10070b57cec5SDimitry Andric 10080b57cec5SDimitry Andrictemplate <class _Tp, class _Up> 1009*cb14a3feSDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr enable_if_t< 1010*cb14a3feSDimitry Andric is_convertible_v<decltype(std::declval<const _Tp&>() < std::declval<const _Up&>()), bool>, 1011*cb14a3feSDimitry Andric bool > 1012*cb14a3feSDimitry Andricoperator<(const optional<_Tp>& __x, const optional<_Up>& __y) { 10130b57cec5SDimitry Andric if (!static_cast<bool>(__y)) 10140b57cec5SDimitry Andric return false; 10150b57cec5SDimitry Andric if (!static_cast<bool>(__x)) 10160b57cec5SDimitry Andric return true; 10170b57cec5SDimitry Andric return *__x < *__y; 10180b57cec5SDimitry Andric} 10190b57cec5SDimitry Andric 10200b57cec5SDimitry Andrictemplate <class _Tp, class _Up> 1021*cb14a3feSDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr enable_if_t< 1022*cb14a3feSDimitry Andric is_convertible_v<decltype(std::declval<const _Tp&>() > std::declval<const _Up&>()), bool>, 1023*cb14a3feSDimitry Andric bool > 1024*cb14a3feSDimitry Andricoperator>(const optional<_Tp>& __x, const optional<_Up>& __y) { 10250b57cec5SDimitry Andric if (!static_cast<bool>(__x)) 10260b57cec5SDimitry Andric return false; 10270b57cec5SDimitry Andric if (!static_cast<bool>(__y)) 10280b57cec5SDimitry Andric return true; 10290b57cec5SDimitry Andric return *__x > *__y; 10300b57cec5SDimitry Andric} 10310b57cec5SDimitry Andric 10320b57cec5SDimitry Andrictemplate <class _Tp, class _Up> 1033*cb14a3feSDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr enable_if_t< 1034*cb14a3feSDimitry Andric is_convertible_v<decltype(std::declval<const _Tp&>() <= std::declval<const _Up&>()), bool>, 1035*cb14a3feSDimitry Andric bool > 1036*cb14a3feSDimitry Andricoperator<=(const optional<_Tp>& __x, const optional<_Up>& __y) { 10370b57cec5SDimitry Andric if (!static_cast<bool>(__x)) 10380b57cec5SDimitry Andric return true; 10390b57cec5SDimitry Andric if (!static_cast<bool>(__y)) 10400b57cec5SDimitry Andric return false; 10410b57cec5SDimitry Andric return *__x <= *__y; 10420b57cec5SDimitry Andric} 10430b57cec5SDimitry Andric 10440b57cec5SDimitry Andrictemplate <class _Tp, class _Up> 1045*cb14a3feSDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr enable_if_t< 1046*cb14a3feSDimitry Andric is_convertible_v<decltype(std::declval<const _Tp&>() >= std::declval<const _Up&>()), bool>, 1047*cb14a3feSDimitry Andric bool > 1048*cb14a3feSDimitry Andricoperator>=(const optional<_Tp>& __x, const optional<_Up>& __y) { 10490b57cec5SDimitry Andric if (!static_cast<bool>(__y)) 10500b57cec5SDimitry Andric return true; 10510b57cec5SDimitry Andric if (!static_cast<bool>(__x)) 10520b57cec5SDimitry Andric return false; 10530b57cec5SDimitry Andric return *__x >= *__y; 10540b57cec5SDimitry Andric} 10550b57cec5SDimitry Andric 105606c3fb27SDimitry Andric# if _LIBCPP_STD_VER >= 20 105706c3fb27SDimitry Andric 105806c3fb27SDimitry Andrictemplate <class _Tp, three_way_comparable_with<_Tp> _Up> 105906c3fb27SDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr compare_three_way_result_t<_Tp, _Up> 106006c3fb27SDimitry Andricoperator<=>(const optional<_Tp>& __x, const optional<_Up>& __y) { 106106c3fb27SDimitry Andric if (__x && __y) 106206c3fb27SDimitry Andric return *__x <=> *__y; 106306c3fb27SDimitry Andric return __x.has_value() <=> __y.has_value(); 106406c3fb27SDimitry Andric} 106506c3fb27SDimitry Andric 106606c3fb27SDimitry Andric# endif // _LIBCPP_STD_VER >= 20 106706c3fb27SDimitry Andric 10680b57cec5SDimitry Andric// Comparisons with nullopt 10690b57cec5SDimitry Andrictemplate <class _Tp> 1070*cb14a3feSDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr bool operator==(const optional<_Tp>& __x, nullopt_t) noexcept { 10710b57cec5SDimitry Andric return !static_cast<bool>(__x); 10720b57cec5SDimitry Andric} 10730b57cec5SDimitry Andric 107406c3fb27SDimitry Andric# if _LIBCPP_STD_VER <= 17 107506c3fb27SDimitry Andric 10760b57cec5SDimitry Andrictemplate <class _Tp> 1077*cb14a3feSDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr bool operator==(nullopt_t, const optional<_Tp>& __x) noexcept { 10780b57cec5SDimitry Andric return !static_cast<bool>(__x); 10790b57cec5SDimitry Andric} 10800b57cec5SDimitry Andric 10810b57cec5SDimitry Andrictemplate <class _Tp> 1082*cb14a3feSDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr bool operator!=(const optional<_Tp>& __x, nullopt_t) noexcept { 10830b57cec5SDimitry Andric return static_cast<bool>(__x); 10840b57cec5SDimitry Andric} 10850b57cec5SDimitry Andric 10860b57cec5SDimitry Andrictemplate <class _Tp> 1087*cb14a3feSDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr bool operator!=(nullopt_t, const optional<_Tp>& __x) noexcept { 10880b57cec5SDimitry Andric return static_cast<bool>(__x); 10890b57cec5SDimitry Andric} 10900b57cec5SDimitry Andric 10910b57cec5SDimitry Andrictemplate <class _Tp> 1092*cb14a3feSDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr bool operator<(const optional<_Tp>&, nullopt_t) noexcept { 10930b57cec5SDimitry Andric return false; 10940b57cec5SDimitry Andric} 10950b57cec5SDimitry Andric 10960b57cec5SDimitry Andrictemplate <class _Tp> 1097*cb14a3feSDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr bool operator<(nullopt_t, const optional<_Tp>& __x) noexcept { 10980b57cec5SDimitry Andric return static_cast<bool>(__x); 10990b57cec5SDimitry Andric} 11000b57cec5SDimitry Andric 11010b57cec5SDimitry Andrictemplate <class _Tp> 1102*cb14a3feSDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr bool operator<=(const optional<_Tp>& __x, nullopt_t) noexcept { 11030b57cec5SDimitry Andric return !static_cast<bool>(__x); 11040b57cec5SDimitry Andric} 11050b57cec5SDimitry Andric 11060b57cec5SDimitry Andrictemplate <class _Tp> 1107*cb14a3feSDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr bool operator<=(nullopt_t, const optional<_Tp>&) noexcept { 11080b57cec5SDimitry Andric return true; 11090b57cec5SDimitry Andric} 11100b57cec5SDimitry Andric 11110b57cec5SDimitry Andrictemplate <class _Tp> 1112*cb14a3feSDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr bool operator>(const optional<_Tp>& __x, nullopt_t) noexcept { 11130b57cec5SDimitry Andric return static_cast<bool>(__x); 11140b57cec5SDimitry Andric} 11150b57cec5SDimitry Andric 11160b57cec5SDimitry Andrictemplate <class _Tp> 1117*cb14a3feSDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr bool operator>(nullopt_t, const optional<_Tp>&) noexcept { 11180b57cec5SDimitry Andric return false; 11190b57cec5SDimitry Andric} 11200b57cec5SDimitry Andric 11210b57cec5SDimitry Andrictemplate <class _Tp> 1122*cb14a3feSDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr bool operator>=(const optional<_Tp>&, nullopt_t) noexcept { 11230b57cec5SDimitry Andric return true; 11240b57cec5SDimitry Andric} 11250b57cec5SDimitry Andric 11260b57cec5SDimitry Andrictemplate <class _Tp> 1127*cb14a3feSDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr bool operator>=(nullopt_t, const optional<_Tp>& __x) noexcept { 11280b57cec5SDimitry Andric return !static_cast<bool>(__x); 11290b57cec5SDimitry Andric} 11300b57cec5SDimitry Andric 113106c3fb27SDimitry Andric# else // _LIBCPP_STD_VER <= 17 113206c3fb27SDimitry Andric 113306c3fb27SDimitry Andrictemplate <class _Tp> 113406c3fb27SDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr strong_ordering operator<=>(const optional<_Tp>& __x, nullopt_t) noexcept { 113506c3fb27SDimitry Andric return __x.has_value() <=> false; 113606c3fb27SDimitry Andric} 113706c3fb27SDimitry Andric 113806c3fb27SDimitry Andric# endif // _LIBCPP_STD_VER <= 17 113906c3fb27SDimitry Andric 11400b57cec5SDimitry Andric// Comparisons with T 11410b57cec5SDimitry Andrictemplate <class _Tp, class _Up> 1142*cb14a3feSDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr enable_if_t< 1143*cb14a3feSDimitry Andric is_convertible_v<decltype(std::declval<const _Tp&>() == std::declval<const _Up&>()), bool>, 1144*cb14a3feSDimitry Andric bool > 1145*cb14a3feSDimitry Andricoperator==(const optional<_Tp>& __x, const _Up& __v) { 11460b57cec5SDimitry Andric return static_cast<bool>(__x) ? *__x == __v : false; 11470b57cec5SDimitry Andric} 11480b57cec5SDimitry Andric 11490b57cec5SDimitry Andrictemplate <class _Tp, class _Up> 1150*cb14a3feSDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr enable_if_t< 1151*cb14a3feSDimitry Andric is_convertible_v<decltype(std::declval<const _Tp&>() == std::declval<const _Up&>()), bool>, 1152*cb14a3feSDimitry Andric bool > 1153*cb14a3feSDimitry Andricoperator==(const _Tp& __v, const optional<_Up>& __x) { 11540b57cec5SDimitry Andric return static_cast<bool>(__x) ? __v == *__x : false; 11550b57cec5SDimitry Andric} 11560b57cec5SDimitry Andric 11570b57cec5SDimitry Andrictemplate <class _Tp, class _Up> 1158*cb14a3feSDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr enable_if_t< 1159*cb14a3feSDimitry Andric is_convertible_v<decltype(std::declval<const _Tp&>() != std::declval<const _Up&>()), bool>, 1160*cb14a3feSDimitry Andric bool > 1161*cb14a3feSDimitry Andricoperator!=(const optional<_Tp>& __x, const _Up& __v) { 11620b57cec5SDimitry Andric return static_cast<bool>(__x) ? *__x != __v : true; 11630b57cec5SDimitry Andric} 11640b57cec5SDimitry Andric 11650b57cec5SDimitry Andrictemplate <class _Tp, class _Up> 1166*cb14a3feSDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr enable_if_t< 1167*cb14a3feSDimitry Andric is_convertible_v<decltype(std::declval<const _Tp&>() != std::declval<const _Up&>()), bool>, 1168*cb14a3feSDimitry Andric bool > 1169*cb14a3feSDimitry Andricoperator!=(const _Tp& __v, const optional<_Up>& __x) { 11700b57cec5SDimitry Andric return static_cast<bool>(__x) ? __v != *__x : true; 11710b57cec5SDimitry Andric} 11720b57cec5SDimitry Andric 11730b57cec5SDimitry Andrictemplate <class _Tp, class _Up> 1174*cb14a3feSDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr enable_if_t< 1175*cb14a3feSDimitry Andric is_convertible_v<decltype(std::declval<const _Tp&>() < std::declval<const _Up&>()), bool>, 1176*cb14a3feSDimitry Andric bool > 1177*cb14a3feSDimitry Andricoperator<(const optional<_Tp>& __x, const _Up& __v) { 11780b57cec5SDimitry Andric return static_cast<bool>(__x) ? *__x < __v : true; 11790b57cec5SDimitry Andric} 11800b57cec5SDimitry Andric 11810b57cec5SDimitry Andrictemplate <class _Tp, class _Up> 1182*cb14a3feSDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr enable_if_t< 1183*cb14a3feSDimitry Andric is_convertible_v<decltype(std::declval<const _Tp&>() < std::declval<const _Up&>()), bool>, 1184*cb14a3feSDimitry Andric bool > 1185*cb14a3feSDimitry Andricoperator<(const _Tp& __v, const optional<_Up>& __x) { 11860b57cec5SDimitry Andric return static_cast<bool>(__x) ? __v < *__x : false; 11870b57cec5SDimitry Andric} 11880b57cec5SDimitry Andric 11890b57cec5SDimitry Andrictemplate <class _Tp, class _Up> 1190*cb14a3feSDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr enable_if_t< 1191*cb14a3feSDimitry Andric is_convertible_v<decltype(std::declval<const _Tp&>() <= std::declval<const _Up&>()), bool>, 1192*cb14a3feSDimitry Andric bool > 1193*cb14a3feSDimitry Andricoperator<=(const optional<_Tp>& __x, const _Up& __v) { 11940b57cec5SDimitry Andric return static_cast<bool>(__x) ? *__x <= __v : true; 11950b57cec5SDimitry Andric} 11960b57cec5SDimitry Andric 11970b57cec5SDimitry Andrictemplate <class _Tp, class _Up> 1198*cb14a3feSDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr enable_if_t< 1199*cb14a3feSDimitry Andric is_convertible_v<decltype(std::declval<const _Tp&>() <= std::declval<const _Up&>()), bool>, 1200*cb14a3feSDimitry Andric bool > 1201*cb14a3feSDimitry Andricoperator<=(const _Tp& __v, const optional<_Up>& __x) { 12020b57cec5SDimitry Andric return static_cast<bool>(__x) ? __v <= *__x : false; 12030b57cec5SDimitry Andric} 12040b57cec5SDimitry Andric 12050b57cec5SDimitry Andrictemplate <class _Tp, class _Up> 1206*cb14a3feSDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr enable_if_t< 1207*cb14a3feSDimitry Andric is_convertible_v<decltype(std::declval<const _Tp&>() > std::declval<const _Up&>()), bool>, 1208*cb14a3feSDimitry Andric bool > 1209*cb14a3feSDimitry Andricoperator>(const optional<_Tp>& __x, const _Up& __v) { 12100b57cec5SDimitry Andric return static_cast<bool>(__x) ? *__x > __v : false; 12110b57cec5SDimitry Andric} 12120b57cec5SDimitry Andric 12130b57cec5SDimitry Andrictemplate <class _Tp, class _Up> 1214*cb14a3feSDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr enable_if_t< 1215*cb14a3feSDimitry Andric is_convertible_v<decltype(std::declval<const _Tp&>() > std::declval<const _Up&>()), bool>, 1216*cb14a3feSDimitry Andric bool > 1217*cb14a3feSDimitry Andricoperator>(const _Tp& __v, const optional<_Up>& __x) { 12180b57cec5SDimitry Andric return static_cast<bool>(__x) ? __v > *__x : true; 12190b57cec5SDimitry Andric} 12200b57cec5SDimitry Andric 12210b57cec5SDimitry Andrictemplate <class _Tp, class _Up> 1222*cb14a3feSDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr enable_if_t< 1223*cb14a3feSDimitry Andric is_convertible_v<decltype(std::declval<const _Tp&>() >= std::declval<const _Up&>()), bool>, 1224*cb14a3feSDimitry Andric bool > 1225*cb14a3feSDimitry Andricoperator>=(const optional<_Tp>& __x, const _Up& __v) { 12260b57cec5SDimitry Andric return static_cast<bool>(__x) ? *__x >= __v : false; 12270b57cec5SDimitry Andric} 12280b57cec5SDimitry Andric 12290b57cec5SDimitry Andrictemplate <class _Tp, class _Up> 1230*cb14a3feSDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr enable_if_t< 1231*cb14a3feSDimitry Andric is_convertible_v<decltype(std::declval<const _Tp&>() >= std::declval<const _Up&>()), bool>, 1232*cb14a3feSDimitry Andric bool > 1233*cb14a3feSDimitry Andricoperator>=(const _Tp& __v, const optional<_Up>& __x) { 12340b57cec5SDimitry Andric return static_cast<bool>(__x) ? __v >= *__x : true; 12350b57cec5SDimitry Andric} 12360b57cec5SDimitry Andric 123706c3fb27SDimitry Andric# if _LIBCPP_STD_VER >= 20 123806c3fb27SDimitry Andric 123906c3fb27SDimitry Andrictemplate <class _Tp, class _Up> 124006c3fb27SDimitry Andric requires(!__is_derived_from_optional<_Up>) && three_way_comparable_with<_Tp, _Up> 124106c3fb27SDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr compare_three_way_result_t<_Tp, _Up> 124206c3fb27SDimitry Andricoperator<=>(const optional<_Tp>& __x, const _Up& __v) { 124306c3fb27SDimitry Andric return __x.has_value() ? *__x <=> __v : strong_ordering::less; 124406c3fb27SDimitry Andric} 124506c3fb27SDimitry Andric 124606c3fb27SDimitry Andric# endif // _LIBCPP_STD_VER >= 20 124706c3fb27SDimitry Andric 12480b57cec5SDimitry Andrictemplate <class _Tp> 12495f757f3fSDimitry Andricinline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 1250*cb14a3feSDimitry Andric enable_if_t< is_move_constructible_v<_Tp> && is_swappable_v<_Tp>, void > 1251*cb14a3feSDimitry Andric swap(optional<_Tp>& __x, optional<_Tp>& __y) noexcept(noexcept(__x.swap(__y))) { 12520b57cec5SDimitry Andric __x.swap(__y); 12530b57cec5SDimitry Andric} 12540b57cec5SDimitry Andric 12550b57cec5SDimitry Andrictemplate <class _Tp> 1256*cb14a3feSDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr optional<decay_t<_Tp>> make_optional(_Tp&& __v) { 12575f757f3fSDimitry Andric return optional<decay_t<_Tp>>(std::forward<_Tp>(__v)); 12580b57cec5SDimitry Andric} 12590b57cec5SDimitry Andric 12600b57cec5SDimitry Andrictemplate <class _Tp, class... _Args> 1261*cb14a3feSDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr optional<_Tp> make_optional(_Args&&... __args) { 12625f757f3fSDimitry Andric return optional<_Tp>(in_place, std::forward<_Args>(__args)...); 12630b57cec5SDimitry Andric} 12640b57cec5SDimitry Andric 12650b57cec5SDimitry Andrictemplate <class _Tp, class _Up, class... _Args> 1266*cb14a3feSDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr optional<_Tp> make_optional(initializer_list<_Up> __il, _Args&&... __args) { 12675f757f3fSDimitry Andric return optional<_Tp>(in_place, __il, std::forward<_Args>(__args)...); 12680b57cec5SDimitry Andric} 12690b57cec5SDimitry Andric 12700b57cec5SDimitry Andrictemplate <class _Tp> 1271*cb14a3feSDimitry Andricstruct _LIBCPP_TEMPLATE_VIS hash< __enable_hash_helper<optional<_Tp>, remove_const_t<_Tp>> > { 1272fe6060f1SDimitry Andric# if _LIBCPP_STD_VER <= 17 || defined(_LIBCPP_ENABLE_CXX20_REMOVED_BINDER_TYPEDEFS) 1273fe6060f1SDimitry Andric _LIBCPP_DEPRECATED_IN_CXX17 typedef optional<_Tp> argument_type; 1274fe6060f1SDimitry Andric _LIBCPP_DEPRECATED_IN_CXX17 typedef size_t result_type; 1275fe6060f1SDimitry Andric# endif 12760b57cec5SDimitry Andric 1277*cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI size_t operator()(const optional<_Tp>& __opt) const { 12780b57cec5SDimitry Andric return static_cast<bool>(__opt) ? hash<remove_const_t<_Tp>>()(*__opt) : 0; 12790b57cec5SDimitry Andric } 12800b57cec5SDimitry Andric}; 12810b57cec5SDimitry Andric 12820b57cec5SDimitry Andric_LIBCPP_END_NAMESPACE_STD 12830b57cec5SDimitry Andric 128406c3fb27SDimitry Andric#endif // _LIBCPP_STD_VER >= 17 128506c3fb27SDimitry Andric 128606c3fb27SDimitry Andric_LIBCPP_POP_MACROS 12870b57cec5SDimitry Andric 1288bdd1243dSDimitry Andric#if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER <= 20 1289bdd1243dSDimitry Andric# include <atomic> 1290bdd1243dSDimitry Andric# include <climits> 1291bdd1243dSDimitry Andric# include <concepts> 1292bdd1243dSDimitry Andric# include <ctime> 1293bdd1243dSDimitry Andric# include <iterator> 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