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 { 190b57cec5SDimitry Andric // 23.6.3, optional for object types 200b57cec5SDimitry Andric template <class T> class optional; 210b57cec5SDimitry Andric 220b57cec5SDimitry Andric // 23.6.4, no-value state indicator 230b57cec5SDimitry Andric struct nullopt_t{see below }; 240b57cec5SDimitry Andric inline constexpr nullopt_t nullopt(unspecified ); 250b57cec5SDimitry Andric 260b57cec5SDimitry Andric // 23.6.5, class bad_optional_access 270b57cec5SDimitry Andric class bad_optional_access; 280b57cec5SDimitry Andric 290b57cec5SDimitry Andric // 23.6.6, relational operators 300b57cec5SDimitry Andric template <class T, class U> 310b57cec5SDimitry Andric constexpr bool operator==(const optional<T>&, const optional<U>&); 320b57cec5SDimitry Andric template <class T, class U> 330b57cec5SDimitry Andric constexpr bool operator!=(const optional<T>&, const optional<U>&); 340b57cec5SDimitry Andric template <class T, class U> 350b57cec5SDimitry Andric constexpr bool operator<(const optional<T>&, const optional<U>&); 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 430b57cec5SDimitry Andric // 23.6.7 comparison with nullopt 440b57cec5SDimitry Andric template <class T> constexpr bool operator==(const optional<T>&, nullopt_t) noexcept; 450b57cec5SDimitry Andric template <class T> constexpr bool operator==(nullopt_t, const optional<T>&) noexcept; 460b57cec5SDimitry Andric template <class T> constexpr bool operator!=(const optional<T>&, nullopt_t) noexcept; 470b57cec5SDimitry Andric template <class T> constexpr bool operator!=(nullopt_t, const optional<T>&) noexcept; 480b57cec5SDimitry Andric template <class T> constexpr bool operator<(const optional<T>&, nullopt_t) noexcept; 490b57cec5SDimitry Andric template <class T> constexpr bool operator<(nullopt_t, const optional<T>&) noexcept; 500b57cec5SDimitry Andric template <class T> constexpr bool operator<=(const optional<T>&, nullopt_t) noexcept; 510b57cec5SDimitry Andric template <class T> constexpr bool operator<=(nullopt_t, const optional<T>&) noexcept; 520b57cec5SDimitry Andric template <class T> constexpr bool operator>(const optional<T>&, nullopt_t) noexcept; 530b57cec5SDimitry Andric template <class T> constexpr bool operator>(nullopt_t, const optional<T>&) noexcept; 540b57cec5SDimitry Andric template <class T> constexpr bool operator>=(const optional<T>&, nullopt_t) noexcept; 550b57cec5SDimitry Andric template <class T> constexpr bool operator>=(nullopt_t, const optional<T>&) noexcept; 560b57cec5SDimitry Andric 570b57cec5SDimitry Andric // 23.6.8, comparison with T 580b57cec5SDimitry Andric template <class T, class U> constexpr bool operator==(const optional<T>&, const U&); 590b57cec5SDimitry Andric template <class T, class U> constexpr bool operator==(const T&, const optional<U>&); 600b57cec5SDimitry Andric template <class T, class U> constexpr bool operator!=(const optional<T>&, const U&); 610b57cec5SDimitry Andric template <class T, class U> constexpr bool operator!=(const T&, const optional<U>&); 620b57cec5SDimitry Andric template <class T, class U> constexpr bool operator<(const optional<T>&, const U&); 630b57cec5SDimitry Andric template <class T, class U> constexpr bool operator<(const T&, const optional<U>&); 640b57cec5SDimitry Andric template <class T, class U> constexpr bool operator<=(const optional<T>&, const U&); 650b57cec5SDimitry Andric template <class T, class U> constexpr bool operator<=(const T&, const optional<U>&); 660b57cec5SDimitry Andric template <class T, class U> constexpr bool operator>(const optional<T>&, const U&); 670b57cec5SDimitry Andric template <class T, class U> constexpr bool operator>(const T&, const optional<U>&); 680b57cec5SDimitry Andric template <class T, class U> constexpr bool operator>=(const optional<T>&, const U&); 690b57cec5SDimitry Andric template <class T, class U> constexpr bool operator>=(const T&, const optional<U>&); 700b57cec5SDimitry Andric 710b57cec5SDimitry Andric // 23.6.9, specialized algorithms 72fe6060f1SDimitry Andric template <class T> void swap(optional<T>&, optional<T>&) noexcept(see below ); // constexpr in C++20 730b57cec5SDimitry Andric template <class T> constexpr optional<see below > make_optional(T&&); 740b57cec5SDimitry Andric template <class T, class... Args> 750b57cec5SDimitry Andric constexpr optional<T> make_optional(Args&&... args); 760b57cec5SDimitry Andric template <class T, class U, class... Args> 770b57cec5SDimitry Andric constexpr optional<T> make_optional(initializer_list<U> il, Args&&... args); 780b57cec5SDimitry Andric 790b57cec5SDimitry Andric // 23.6.10, hash support 800b57cec5SDimitry Andric template <class T> struct hash; 810b57cec5SDimitry Andric template <class T> struct hash<optional<T>>; 820b57cec5SDimitry Andric 830b57cec5SDimitry Andric template <class T> class optional { 840b57cec5SDimitry Andric public: 850b57cec5SDimitry Andric using value_type = T; 860b57cec5SDimitry Andric 870b57cec5SDimitry Andric // 23.6.3.1, constructors 880b57cec5SDimitry Andric constexpr optional() noexcept; 890b57cec5SDimitry Andric constexpr optional(nullopt_t) noexcept; 90*bdd1243dSDimitry Andric constexpr optional(const optional &); 91*bdd1243dSDimitry Andric constexpr optional(optional &&) noexcept(see below); 920b57cec5SDimitry Andric template <class... Args> constexpr explicit optional(in_place_t, Args &&...); 930b57cec5SDimitry Andric template <class U, class... Args> 940b57cec5SDimitry Andric constexpr explicit optional(in_place_t, initializer_list<U>, Args &&...); 950b57cec5SDimitry Andric template <class U = T> 9681ad6265SDimitry Andric constexpr explicit(see-below) optional(U &&); 970b57cec5SDimitry Andric template <class U> 9881ad6265SDimitry Andric explicit(see-below) optional(const optional<U> &); // constexpr in C++20 990b57cec5SDimitry Andric template <class U> 10081ad6265SDimitry Andric explicit(see-below) optional(optional<U> &&); // constexpr in C++20 1010b57cec5SDimitry Andric 1020b57cec5SDimitry Andric // 23.6.3.2, destructor 103fe6060f1SDimitry Andric ~optional(); // constexpr in C++20 1040b57cec5SDimitry Andric 1050b57cec5SDimitry Andric // 23.6.3.3, assignment 106fe6060f1SDimitry Andric optional &operator=(nullopt_t) noexcept; // constexpr in C++20 107*bdd1243dSDimitry Andric constexpr optional &operator=(const optional &); 108*bdd1243dSDimitry Andric constexpr optional &operator=(optional &&) noexcept(see below); 109fe6060f1SDimitry Andric template <class U = T> optional &operator=(U &&); // constexpr in C++20 110fe6060f1SDimitry Andric template <class U> optional &operator=(const optional<U> &); // constexpr in C++20 111fe6060f1SDimitry Andric template <class U> optional &operator=(optional<U> &&); // constexpr in C++20 112fe6060f1SDimitry Andric template <class... Args> T& emplace(Args &&...); // constexpr in C++20 1130b57cec5SDimitry Andric template <class U, class... Args> 114fe6060f1SDimitry Andric T& emplace(initializer_list<U>, Args &&...); // constexpr in C++20 1150b57cec5SDimitry Andric 1160b57cec5SDimitry Andric // 23.6.3.4, swap 117fe6060f1SDimitry Andric void swap(optional &) noexcept(see below ); // constexpr in C++20 1180b57cec5SDimitry Andric 1190b57cec5SDimitry Andric // 23.6.3.5, observers 1200b57cec5SDimitry Andric constexpr T const *operator->() const; 1210b57cec5SDimitry Andric constexpr T *operator->(); 1220b57cec5SDimitry Andric constexpr T const &operator*() const &; 1230b57cec5SDimitry Andric constexpr T &operator*() &; 1240b57cec5SDimitry Andric constexpr T &&operator*() &&; 1250b57cec5SDimitry Andric constexpr const T &&operator*() const &&; 1260b57cec5SDimitry Andric constexpr explicit operator bool() const noexcept; 1270b57cec5SDimitry Andric constexpr bool has_value() const noexcept; 1280b57cec5SDimitry Andric constexpr T const &value() const &; 1290b57cec5SDimitry Andric constexpr T &value() &; 1300b57cec5SDimitry Andric constexpr T &&value() &&; 1310b57cec5SDimitry Andric constexpr const T &&value() const &&; 1320b57cec5SDimitry Andric template <class U> constexpr T value_or(U &&) const &; 1330b57cec5SDimitry Andric template <class U> constexpr T value_or(U &&) &&; 1340b57cec5SDimitry Andric 1350eae32dcSDimitry Andric // [optional.monadic], monadic operations 1360eae32dcSDimitry Andric template<class F> constexpr auto and_then(F&& f) &; // since C++23 1370eae32dcSDimitry Andric template<class F> constexpr auto and_then(F&& f) &&; // since C++23 1380eae32dcSDimitry Andric template<class F> constexpr auto and_then(F&& f) const&; // since C++23 1390eae32dcSDimitry Andric template<class F> constexpr auto and_then(F&& f) const&&; // since C++23 1400eae32dcSDimitry Andric template<class F> constexpr auto transform(F&& f) &; // since C++23 1410eae32dcSDimitry Andric template<class F> constexpr auto transform(F&& f) &&; // since C++23 1420eae32dcSDimitry Andric template<class F> constexpr auto transform(F&& f) const&; // since C++23 1430eae32dcSDimitry Andric template<class F> constexpr auto transform(F&& f) const&&; // since C++23 1440eae32dcSDimitry Andric template<class F> constexpr optional or_else(F&& f) &&; // since C++23 1450eae32dcSDimitry Andric template<class F> constexpr optional or_else(F&& f) const&; // since C++23 1460eae32dcSDimitry Andric 1470b57cec5SDimitry Andric // 23.6.3.6, modifiers 148fe6060f1SDimitry Andric void reset() noexcept; // constexpr in C++20 1490b57cec5SDimitry Andric 1500b57cec5SDimitry Andric private: 1510b57cec5SDimitry Andric T *val; // exposition only 1520b57cec5SDimitry Andric }; 1530b57cec5SDimitry Andric 1540b57cec5SDimitry Andrictemplate<class T> 1550b57cec5SDimitry Andric optional(T) -> optional<T>; 1560b57cec5SDimitry Andric 1570b57cec5SDimitry Andric} // namespace std 1580b57cec5SDimitry Andric 1590b57cec5SDimitry Andric*/ 1600b57cec5SDimitry Andric 16181ad6265SDimitry Andric#include <__assert> // all public C++ headers provide the assertion handler 162e8d8bef9SDimitry Andric#include <__availability> 1630eae32dcSDimitry Andric#include <__concepts/invocable.h> 164fe6060f1SDimitry Andric#include <__config> 16581ad6265SDimitry Andric#include <__functional/hash.h> 16681ad6265SDimitry Andric#include <__functional/invoke.h> 16781ad6265SDimitry Andric#include <__functional/unary_function.h> 16881ad6265SDimitry Andric#include <__memory/construct_at.h> 169*bdd1243dSDimitry Andric#include <__tuple_dir/sfinae_helpers.h> 17081ad6265SDimitry Andric#include <__utility/forward.h> 17181ad6265SDimitry Andric#include <__utility/in_place.h> 17281ad6265SDimitry Andric#include <__utility/move.h> 17381ad6265SDimitry Andric#include <__utility/swap.h> 1740b57cec5SDimitry Andric#include <initializer_list> 1750b57cec5SDimitry Andric#include <new> 1760b57cec5SDimitry Andric#include <stdexcept> 1770b57cec5SDimitry Andric#include <type_traits> 1780b57cec5SDimitry Andric#include <version> 1790b57cec5SDimitry Andric 18081ad6265SDimitry Andric// standard-mandated includes 181*bdd1243dSDimitry Andric 182*bdd1243dSDimitry Andric// [optional.syn] 18381ad6265SDimitry Andric#include <compare> 18481ad6265SDimitry Andric 1850b57cec5SDimitry Andric#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 1860b57cec5SDimitry Andric# pragma GCC system_header 1870b57cec5SDimitry Andric#endif 1880b57cec5SDimitry Andric 1890b57cec5SDimitry Andricnamespace std // purposefully not using versioning namespace 1900b57cec5SDimitry Andric{ 1910b57cec5SDimitry Andric 1920b57cec5SDimitry Andricclass _LIBCPP_EXCEPTION_ABI _LIBCPP_AVAILABILITY_BAD_OPTIONAL_ACCESS bad_optional_access 1930b57cec5SDimitry Andric : public exception 1940b57cec5SDimitry Andric{ 1950b57cec5SDimitry Andricpublic: 1960b57cec5SDimitry Andric // Get the key function ~bad_optional_access() into the dylib 197*bdd1243dSDimitry Andric ~bad_optional_access() _NOEXCEPT override; 198*bdd1243dSDimitry Andric const char* what() const _NOEXCEPT override; 1990b57cec5SDimitry Andric}; 2000b57cec5SDimitry Andric 2010eae32dcSDimitry Andric} // namespace std 2020b57cec5SDimitry Andric 2030b57cec5SDimitry Andric#if _LIBCPP_STD_VER > 14 2040b57cec5SDimitry Andric 2050b57cec5SDimitry Andric_LIBCPP_BEGIN_NAMESPACE_STD 2060b57cec5SDimitry Andric 2070b57cec5SDimitry Andric_LIBCPP_NORETURN 2080b57cec5SDimitry Andricinline _LIBCPP_INLINE_VISIBILITY 2090b57cec5SDimitry Andric_LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS 2100b57cec5SDimitry Andricvoid __throw_bad_optional_access() { 2110b57cec5SDimitry Andric#ifndef _LIBCPP_NO_EXCEPTIONS 2120b57cec5SDimitry Andric throw bad_optional_access(); 2130b57cec5SDimitry Andric#else 2140b57cec5SDimitry Andric _VSTD::abort(); 2150b57cec5SDimitry Andric#endif 2160b57cec5SDimitry Andric} 2170b57cec5SDimitry Andric 2180b57cec5SDimitry Andricstruct nullopt_t 2190b57cec5SDimitry Andric{ 2200b57cec5SDimitry Andric struct __secret_tag { _LIBCPP_INLINE_VISIBILITY explicit __secret_tag() = default; }; 2210b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY constexpr explicit nullopt_t(__secret_tag, __secret_tag) noexcept {} 2220b57cec5SDimitry Andric}; 2230b57cec5SDimitry Andric 224349cc55cSDimitry Andricinline constexpr nullopt_t nullopt{nullopt_t::__secret_tag{}, nullopt_t::__secret_tag{}}; 2250b57cec5SDimitry Andric 2260eae32dcSDimitry Andricstruct __optional_construct_from_invoke_tag {}; 2270eae32dcSDimitry Andric 2280b57cec5SDimitry Andrictemplate <class _Tp, bool = is_trivially_destructible<_Tp>::value> 2290b57cec5SDimitry Andricstruct __optional_destruct_base; 2300b57cec5SDimitry Andric 2310b57cec5SDimitry Andrictemplate <class _Tp> 2320b57cec5SDimitry Andricstruct __optional_destruct_base<_Tp, false> 2330b57cec5SDimitry Andric{ 2340b57cec5SDimitry Andric typedef _Tp value_type; 2350b57cec5SDimitry Andric static_assert(is_object_v<value_type>, 2360b57cec5SDimitry Andric "instantiation of optional with a non-object type is undefined behavior"); 2370b57cec5SDimitry Andric union 2380b57cec5SDimitry Andric { 2390b57cec5SDimitry Andric char __null_state_; 2400b57cec5SDimitry Andric value_type __val_; 2410b57cec5SDimitry Andric }; 2420b57cec5SDimitry Andric bool __engaged_; 2430b57cec5SDimitry Andric 2440b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY 245*bdd1243dSDimitry Andric _LIBCPP_CONSTEXPR_SINCE_CXX20 ~__optional_destruct_base() 2460b57cec5SDimitry Andric { 2470b57cec5SDimitry Andric if (__engaged_) 2480b57cec5SDimitry Andric __val_.~value_type(); 2490b57cec5SDimitry Andric } 2500b57cec5SDimitry Andric 2510b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY 2520b57cec5SDimitry Andric constexpr __optional_destruct_base() noexcept 2530b57cec5SDimitry Andric : __null_state_(), 2540b57cec5SDimitry Andric __engaged_(false) {} 2550b57cec5SDimitry Andric 2560b57cec5SDimitry Andric template <class... _Args> 2570b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY 2580b57cec5SDimitry Andric constexpr explicit __optional_destruct_base(in_place_t, _Args&&... __args) 2590b57cec5SDimitry Andric : __val_(_VSTD::forward<_Args>(__args)...), 2600b57cec5SDimitry Andric __engaged_(true) {} 2610b57cec5SDimitry Andric 2620eae32dcSDimitry Andric#if _LIBCPP_STD_VER > 20 2630eae32dcSDimitry Andric template <class _Fp, class... _Args> 2640eae32dcSDimitry Andric _LIBCPP_HIDE_FROM_ABI 2650eae32dcSDimitry Andric constexpr __optional_destruct_base(__optional_construct_from_invoke_tag, _Fp&& __f, _Args&&... __args) 2660eae32dcSDimitry Andric : __val_(_VSTD::invoke(_VSTD::forward<_Fp>(__f), _VSTD::forward<_Args>(__args)...)), __engaged_(true) {} 2670eae32dcSDimitry Andric#endif 2680eae32dcSDimitry Andric 2690b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY 270*bdd1243dSDimitry Andric _LIBCPP_CONSTEXPR_SINCE_CXX20 void reset() noexcept 2710b57cec5SDimitry Andric { 2720b57cec5SDimitry Andric if (__engaged_) 2730b57cec5SDimitry Andric { 2740b57cec5SDimitry Andric __val_.~value_type(); 2750b57cec5SDimitry Andric __engaged_ = false; 2760b57cec5SDimitry Andric } 2770b57cec5SDimitry Andric } 2780b57cec5SDimitry Andric}; 2790b57cec5SDimitry Andric 2800b57cec5SDimitry Andrictemplate <class _Tp> 2810b57cec5SDimitry Andricstruct __optional_destruct_base<_Tp, true> 2820b57cec5SDimitry Andric{ 2830b57cec5SDimitry Andric typedef _Tp value_type; 2840b57cec5SDimitry Andric static_assert(is_object_v<value_type>, 2850b57cec5SDimitry Andric "instantiation of optional with a non-object type is undefined behavior"); 2860b57cec5SDimitry Andric union 2870b57cec5SDimitry Andric { 2880b57cec5SDimitry Andric char __null_state_; 2890b57cec5SDimitry Andric value_type __val_; 2900b57cec5SDimitry Andric }; 2910b57cec5SDimitry Andric bool __engaged_; 2920b57cec5SDimitry Andric 2930b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY 2940b57cec5SDimitry Andric constexpr __optional_destruct_base() noexcept 2950b57cec5SDimitry Andric : __null_state_(), 2960b57cec5SDimitry Andric __engaged_(false) {} 2970b57cec5SDimitry Andric 2980b57cec5SDimitry Andric template <class... _Args> 2990b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY 3000b57cec5SDimitry Andric constexpr explicit __optional_destruct_base(in_place_t, _Args&&... __args) 3010b57cec5SDimitry Andric : __val_(_VSTD::forward<_Args>(__args)...), 3020b57cec5SDimitry Andric __engaged_(true) {} 3030b57cec5SDimitry Andric 3040eae32dcSDimitry Andric#if _LIBCPP_STD_VER > 20 3050eae32dcSDimitry Andric template <class _Fp, class... _Args> 3060eae32dcSDimitry Andric _LIBCPP_HIDE_FROM_ABI 3070eae32dcSDimitry Andric constexpr __optional_destruct_base(__optional_construct_from_invoke_tag, _Fp&& __f, _Args&&... __args) 3080eae32dcSDimitry Andric : __val_(_VSTD::invoke(_VSTD::forward<_Fp>(__f), _VSTD::forward<_Args>(__args)...)), __engaged_(true) {} 3090eae32dcSDimitry Andric#endif 3100eae32dcSDimitry Andric 3110b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY 312*bdd1243dSDimitry Andric _LIBCPP_CONSTEXPR_SINCE_CXX20 void reset() noexcept 3130b57cec5SDimitry Andric { 3140b57cec5SDimitry Andric if (__engaged_) 3150b57cec5SDimitry Andric { 3160b57cec5SDimitry Andric __engaged_ = false; 3170b57cec5SDimitry Andric } 3180b57cec5SDimitry Andric } 3190b57cec5SDimitry Andric}; 3200b57cec5SDimitry Andric 3210b57cec5SDimitry Andrictemplate <class _Tp, bool = is_reference<_Tp>::value> 3220b57cec5SDimitry Andricstruct __optional_storage_base : __optional_destruct_base<_Tp> 3230b57cec5SDimitry Andric{ 3240b57cec5SDimitry Andric using __base = __optional_destruct_base<_Tp>; 3250b57cec5SDimitry Andric using value_type = _Tp; 3260b57cec5SDimitry Andric using __base::__base; 3270b57cec5SDimitry Andric 3280b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY 3290b57cec5SDimitry Andric constexpr bool has_value() const noexcept 3300b57cec5SDimitry Andric { 3310b57cec5SDimitry Andric return this->__engaged_; 3320b57cec5SDimitry Andric } 3330b57cec5SDimitry Andric 3340b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY 3350b57cec5SDimitry Andric constexpr value_type& __get() & noexcept 3360b57cec5SDimitry Andric { 3370b57cec5SDimitry Andric return this->__val_; 3380b57cec5SDimitry Andric } 3390b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY 3400b57cec5SDimitry Andric constexpr const value_type& __get() const& noexcept 3410b57cec5SDimitry Andric { 3420b57cec5SDimitry Andric return this->__val_; 3430b57cec5SDimitry Andric } 3440b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY 3450b57cec5SDimitry Andric constexpr value_type&& __get() && noexcept 3460b57cec5SDimitry Andric { 3470b57cec5SDimitry Andric return _VSTD::move(this->__val_); 3480b57cec5SDimitry Andric } 3490b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY 3500b57cec5SDimitry Andric constexpr const value_type&& __get() const&& noexcept 3510b57cec5SDimitry Andric { 3520b57cec5SDimitry Andric return _VSTD::move(this->__val_); 3530b57cec5SDimitry Andric } 3540b57cec5SDimitry Andric 3550b57cec5SDimitry Andric template <class... _Args> 3560b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY 357*bdd1243dSDimitry Andric _LIBCPP_CONSTEXPR_SINCE_CXX20 void __construct(_Args&&... __args) 3580b57cec5SDimitry Andric { 3590b57cec5SDimitry Andric _LIBCPP_ASSERT(!has_value(), "__construct called for engaged __optional_storage"); 360fe6060f1SDimitry Andric#if _LIBCPP_STD_VER > 17 361fe6060f1SDimitry Andric _VSTD::construct_at(_VSTD::addressof(this->__val_), _VSTD::forward<_Args>(__args)...); 362fe6060f1SDimitry Andric#else 3630b57cec5SDimitry Andric ::new ((void*)_VSTD::addressof(this->__val_)) value_type(_VSTD::forward<_Args>(__args)...); 364fe6060f1SDimitry Andric#endif 3650b57cec5SDimitry Andric this->__engaged_ = true; 3660b57cec5SDimitry Andric } 3670b57cec5SDimitry Andric 3680b57cec5SDimitry Andric template <class _That> 3690b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY 370*bdd1243dSDimitry Andric _LIBCPP_CONSTEXPR_SINCE_CXX20 void __construct_from(_That&& __opt) 3710b57cec5SDimitry Andric { 3720b57cec5SDimitry Andric if (__opt.has_value()) 3730b57cec5SDimitry Andric __construct(_VSTD::forward<_That>(__opt).__get()); 3740b57cec5SDimitry Andric } 3750b57cec5SDimitry Andric 3760b57cec5SDimitry Andric template <class _That> 3770b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY 378*bdd1243dSDimitry Andric _LIBCPP_CONSTEXPR_SINCE_CXX20 void __assign_from(_That&& __opt) 3790b57cec5SDimitry Andric { 3800b57cec5SDimitry Andric if (this->__engaged_ == __opt.has_value()) 3810b57cec5SDimitry Andric { 3820b57cec5SDimitry Andric if (this->__engaged_) 3830b57cec5SDimitry Andric this->__val_ = _VSTD::forward<_That>(__opt).__get(); 3840b57cec5SDimitry Andric } 3850b57cec5SDimitry Andric else 3860b57cec5SDimitry Andric { 3870b57cec5SDimitry Andric if (this->__engaged_) 3880b57cec5SDimitry Andric this->reset(); 3890b57cec5SDimitry Andric else 3900b57cec5SDimitry Andric __construct(_VSTD::forward<_That>(__opt).__get()); 3910b57cec5SDimitry Andric } 3920b57cec5SDimitry Andric } 3930b57cec5SDimitry Andric}; 3940b57cec5SDimitry Andric 39581ad6265SDimitry Andric// optional<T&> is currently required to be ill-formed. However, it may 39681ad6265SDimitry Andric// be allowed in the future. For this reason, it has already been implemented 39781ad6265SDimitry Andric// to ensure we can make the change in an ABI-compatible manner. 3980b57cec5SDimitry Andrictemplate <class _Tp> 3990b57cec5SDimitry Andricstruct __optional_storage_base<_Tp, true> 4000b57cec5SDimitry Andric{ 4010b57cec5SDimitry Andric using value_type = _Tp; 4020b57cec5SDimitry Andric using __raw_type = remove_reference_t<_Tp>; 4030b57cec5SDimitry Andric __raw_type* __value_; 4040b57cec5SDimitry Andric 4050b57cec5SDimitry Andric template <class _Up> 4060b57cec5SDimitry Andric static constexpr bool __can_bind_reference() { 407*bdd1243dSDimitry Andric using _RawUp = __libcpp_remove_reference_t<_Up>; 4080b57cec5SDimitry Andric using _UpPtr = _RawUp*; 409*bdd1243dSDimitry Andric using _RawTp = __libcpp_remove_reference_t<_Tp>; 4100b57cec5SDimitry Andric using _TpPtr = _RawTp*; 4110b57cec5SDimitry Andric using _CheckLValueArg = integral_constant<bool, 4120b57cec5SDimitry Andric (is_lvalue_reference<_Up>::value && is_convertible<_UpPtr, _TpPtr>::value) 4130b57cec5SDimitry Andric || is_same<_RawUp, reference_wrapper<_RawTp>>::value 414*bdd1243dSDimitry Andric || is_same<_RawUp, reference_wrapper<__remove_const_t<_RawTp>>>::value 4150b57cec5SDimitry Andric >; 4160b57cec5SDimitry Andric return (is_lvalue_reference<_Tp>::value && _CheckLValueArg::value) 4170b57cec5SDimitry Andric || (is_rvalue_reference<_Tp>::value && !is_lvalue_reference<_Up>::value && 4180b57cec5SDimitry Andric is_convertible<_UpPtr, _TpPtr>::value); 4190b57cec5SDimitry Andric } 4200b57cec5SDimitry Andric 4210b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY 4220b57cec5SDimitry Andric constexpr __optional_storage_base() noexcept 4230b57cec5SDimitry Andric : __value_(nullptr) {} 4240b57cec5SDimitry Andric 4250b57cec5SDimitry Andric template <class _UArg> 4260b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY 4270b57cec5SDimitry Andric constexpr explicit __optional_storage_base(in_place_t, _UArg&& __uarg) 4280b57cec5SDimitry Andric : __value_(_VSTD::addressof(__uarg)) 4290b57cec5SDimitry Andric { 4300b57cec5SDimitry Andric static_assert(__can_bind_reference<_UArg>(), 4310b57cec5SDimitry Andric "Attempted to construct a reference element in tuple from a " 4320b57cec5SDimitry Andric "possible temporary"); 4330b57cec5SDimitry Andric } 4340b57cec5SDimitry Andric 4350b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY 436*bdd1243dSDimitry Andric _LIBCPP_CONSTEXPR_SINCE_CXX20 void reset() noexcept { __value_ = nullptr; } 4370b57cec5SDimitry Andric 4380b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY 4390b57cec5SDimitry Andric constexpr bool has_value() const noexcept 4400b57cec5SDimitry Andric { return __value_ != nullptr; } 4410b57cec5SDimitry Andric 4420b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY 4430b57cec5SDimitry Andric constexpr value_type& __get() const& noexcept 4440b57cec5SDimitry Andric { return *__value_; } 4450b57cec5SDimitry Andric 4460b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY 4470b57cec5SDimitry Andric constexpr value_type&& __get() const&& noexcept 4480b57cec5SDimitry Andric { return _VSTD::forward<value_type>(*__value_); } 4490b57cec5SDimitry Andric 4500b57cec5SDimitry Andric template <class _UArg> 4510b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY 452*bdd1243dSDimitry Andric _LIBCPP_CONSTEXPR_SINCE_CXX20 void __construct(_UArg&& __val) 4530b57cec5SDimitry Andric { 4540b57cec5SDimitry Andric _LIBCPP_ASSERT(!has_value(), "__construct called for engaged __optional_storage"); 4550b57cec5SDimitry Andric static_assert(__can_bind_reference<_UArg>(), 4560b57cec5SDimitry Andric "Attempted to construct a reference element in tuple from a " 4570b57cec5SDimitry Andric "possible temporary"); 4580b57cec5SDimitry Andric __value_ = _VSTD::addressof(__val); 4590b57cec5SDimitry Andric } 4600b57cec5SDimitry Andric 4610b57cec5SDimitry Andric template <class _That> 4620b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY 463*bdd1243dSDimitry Andric _LIBCPP_CONSTEXPR_SINCE_CXX20 void __construct_from(_That&& __opt) 4640b57cec5SDimitry Andric { 4650b57cec5SDimitry Andric if (__opt.has_value()) 4660b57cec5SDimitry Andric __construct(_VSTD::forward<_That>(__opt).__get()); 4670b57cec5SDimitry Andric } 4680b57cec5SDimitry Andric 4690b57cec5SDimitry Andric template <class _That> 4700b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY 471*bdd1243dSDimitry Andric _LIBCPP_CONSTEXPR_SINCE_CXX20 void __assign_from(_That&& __opt) 4720b57cec5SDimitry Andric { 4730b57cec5SDimitry Andric if (has_value() == __opt.has_value()) 4740b57cec5SDimitry Andric { 4750b57cec5SDimitry Andric if (has_value()) 4760b57cec5SDimitry Andric *__value_ = _VSTD::forward<_That>(__opt).__get(); 4770b57cec5SDimitry Andric } 4780b57cec5SDimitry Andric else 4790b57cec5SDimitry Andric { 4800b57cec5SDimitry Andric if (has_value()) 4810b57cec5SDimitry Andric reset(); 4820b57cec5SDimitry Andric else 4830b57cec5SDimitry Andric __construct(_VSTD::forward<_That>(__opt).__get()); 4840b57cec5SDimitry Andric } 4850b57cec5SDimitry Andric } 4860b57cec5SDimitry Andric}; 4870b57cec5SDimitry Andric 4880b57cec5SDimitry Andrictemplate <class _Tp, bool = is_trivially_copy_constructible<_Tp>::value> 4890b57cec5SDimitry Andricstruct __optional_copy_base : __optional_storage_base<_Tp> 4900b57cec5SDimitry Andric{ 4910b57cec5SDimitry Andric using __optional_storage_base<_Tp>::__optional_storage_base; 4920b57cec5SDimitry Andric}; 4930b57cec5SDimitry Andric 4940b57cec5SDimitry Andrictemplate <class _Tp> 4950b57cec5SDimitry Andricstruct __optional_copy_base<_Tp, false> : __optional_storage_base<_Tp> 4960b57cec5SDimitry Andric{ 4970b57cec5SDimitry Andric using __optional_storage_base<_Tp>::__optional_storage_base; 4980b57cec5SDimitry Andric 4990b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY 5000b57cec5SDimitry Andric __optional_copy_base() = default; 5010b57cec5SDimitry Andric 5020b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY 503*bdd1243dSDimitry Andric _LIBCPP_CONSTEXPR_SINCE_CXX20 __optional_copy_base(const __optional_copy_base& __opt) 5040b57cec5SDimitry Andric { 5050b57cec5SDimitry Andric this->__construct_from(__opt); 5060b57cec5SDimitry Andric } 5070b57cec5SDimitry Andric 5080b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY 5090b57cec5SDimitry Andric __optional_copy_base(__optional_copy_base&&) = default; 5100b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY 5110b57cec5SDimitry Andric __optional_copy_base& operator=(const __optional_copy_base&) = default; 5120b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY 5130b57cec5SDimitry Andric __optional_copy_base& operator=(__optional_copy_base&&) = default; 5140b57cec5SDimitry Andric}; 5150b57cec5SDimitry Andric 5160b57cec5SDimitry Andrictemplate <class _Tp, bool = is_trivially_move_constructible<_Tp>::value> 5170b57cec5SDimitry Andricstruct __optional_move_base : __optional_copy_base<_Tp> 5180b57cec5SDimitry Andric{ 5190b57cec5SDimitry Andric using __optional_copy_base<_Tp>::__optional_copy_base; 5200b57cec5SDimitry Andric}; 5210b57cec5SDimitry Andric 5220b57cec5SDimitry Andrictemplate <class _Tp> 5230b57cec5SDimitry Andricstruct __optional_move_base<_Tp, false> : __optional_copy_base<_Tp> 5240b57cec5SDimitry Andric{ 5250b57cec5SDimitry Andric using value_type = _Tp; 5260b57cec5SDimitry Andric using __optional_copy_base<_Tp>::__optional_copy_base; 5270b57cec5SDimitry Andric 5280b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY 5290b57cec5SDimitry Andric __optional_move_base() = default; 5300b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY 5310b57cec5SDimitry Andric __optional_move_base(const __optional_move_base&) = default; 5320b57cec5SDimitry Andric 5330b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY 534*bdd1243dSDimitry Andric _LIBCPP_CONSTEXPR_SINCE_CXX20 __optional_move_base(__optional_move_base&& __opt) 5350b57cec5SDimitry Andric noexcept(is_nothrow_move_constructible_v<value_type>) 5360b57cec5SDimitry Andric { 5370b57cec5SDimitry Andric this->__construct_from(_VSTD::move(__opt)); 5380b57cec5SDimitry Andric } 5390b57cec5SDimitry Andric 5400b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY 5410b57cec5SDimitry Andric __optional_move_base& operator=(const __optional_move_base&) = default; 5420b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY 5430b57cec5SDimitry Andric __optional_move_base& operator=(__optional_move_base&&) = default; 5440b57cec5SDimitry Andric}; 5450b57cec5SDimitry Andric 5460b57cec5SDimitry Andrictemplate <class _Tp, bool = 5470b57cec5SDimitry Andric is_trivially_destructible<_Tp>::value && 5480b57cec5SDimitry Andric is_trivially_copy_constructible<_Tp>::value && 5490b57cec5SDimitry Andric is_trivially_copy_assignable<_Tp>::value> 5500b57cec5SDimitry Andricstruct __optional_copy_assign_base : __optional_move_base<_Tp> 5510b57cec5SDimitry Andric{ 5520b57cec5SDimitry Andric using __optional_move_base<_Tp>::__optional_move_base; 5530b57cec5SDimitry Andric}; 5540b57cec5SDimitry Andric 5550b57cec5SDimitry Andrictemplate <class _Tp> 5560b57cec5SDimitry Andricstruct __optional_copy_assign_base<_Tp, false> : __optional_move_base<_Tp> 5570b57cec5SDimitry Andric{ 5580b57cec5SDimitry Andric using __optional_move_base<_Tp>::__optional_move_base; 5590b57cec5SDimitry Andric 5600b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY 5610b57cec5SDimitry Andric __optional_copy_assign_base() = default; 5620b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY 5630b57cec5SDimitry Andric __optional_copy_assign_base(const __optional_copy_assign_base&) = default; 5640b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY 5650b57cec5SDimitry Andric __optional_copy_assign_base(__optional_copy_assign_base&&) = default; 5660b57cec5SDimitry Andric 5670b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY 568*bdd1243dSDimitry Andric _LIBCPP_CONSTEXPR_SINCE_CXX20 __optional_copy_assign_base& operator=(const __optional_copy_assign_base& __opt) 5690b57cec5SDimitry Andric { 5700b57cec5SDimitry Andric this->__assign_from(__opt); 5710b57cec5SDimitry Andric return *this; 5720b57cec5SDimitry Andric } 5730b57cec5SDimitry Andric 5740b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY 5750b57cec5SDimitry Andric __optional_copy_assign_base& operator=(__optional_copy_assign_base&&) = default; 5760b57cec5SDimitry Andric}; 5770b57cec5SDimitry Andric 5780b57cec5SDimitry Andrictemplate <class _Tp, bool = 5790b57cec5SDimitry Andric is_trivially_destructible<_Tp>::value && 5800b57cec5SDimitry Andric is_trivially_move_constructible<_Tp>::value && 5810b57cec5SDimitry Andric is_trivially_move_assignable<_Tp>::value> 5820b57cec5SDimitry Andricstruct __optional_move_assign_base : __optional_copy_assign_base<_Tp> 5830b57cec5SDimitry Andric{ 5840b57cec5SDimitry Andric using __optional_copy_assign_base<_Tp>::__optional_copy_assign_base; 5850b57cec5SDimitry Andric}; 5860b57cec5SDimitry Andric 5870b57cec5SDimitry Andrictemplate <class _Tp> 5880b57cec5SDimitry Andricstruct __optional_move_assign_base<_Tp, false> : __optional_copy_assign_base<_Tp> 5890b57cec5SDimitry Andric{ 5900b57cec5SDimitry Andric using value_type = _Tp; 5910b57cec5SDimitry Andric using __optional_copy_assign_base<_Tp>::__optional_copy_assign_base; 5920b57cec5SDimitry Andric 5930b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY 5940b57cec5SDimitry Andric __optional_move_assign_base() = default; 5950b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY 5960b57cec5SDimitry Andric __optional_move_assign_base(const __optional_move_assign_base& __opt) = default; 5970b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY 5980b57cec5SDimitry Andric __optional_move_assign_base(__optional_move_assign_base&&) = default; 5990b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY 6000b57cec5SDimitry Andric __optional_move_assign_base& operator=(const __optional_move_assign_base&) = default; 6010b57cec5SDimitry Andric 6020b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY 603*bdd1243dSDimitry Andric _LIBCPP_CONSTEXPR_SINCE_CXX20 __optional_move_assign_base& operator=(__optional_move_assign_base&& __opt) 6040b57cec5SDimitry Andric noexcept(is_nothrow_move_assignable_v<value_type> && 6050b57cec5SDimitry Andric is_nothrow_move_constructible_v<value_type>) 6060b57cec5SDimitry Andric { 6070b57cec5SDimitry Andric this->__assign_from(_VSTD::move(__opt)); 6080b57cec5SDimitry Andric return *this; 6090b57cec5SDimitry Andric } 6100b57cec5SDimitry Andric}; 6110b57cec5SDimitry Andric 6120b57cec5SDimitry Andrictemplate <class _Tp> 6130b57cec5SDimitry Andricusing __optional_sfinae_ctor_base_t = __sfinae_ctor_base< 6140b57cec5SDimitry Andric is_copy_constructible<_Tp>::value, 6150b57cec5SDimitry Andric is_move_constructible<_Tp>::value 6160b57cec5SDimitry Andric>; 6170b57cec5SDimitry Andric 6180b57cec5SDimitry Andrictemplate <class _Tp> 6190b57cec5SDimitry Andricusing __optional_sfinae_assign_base_t = __sfinae_assign_base< 6200b57cec5SDimitry Andric (is_copy_constructible<_Tp>::value && is_copy_assignable<_Tp>::value), 6210b57cec5SDimitry Andric (is_move_constructible<_Tp>::value && is_move_assignable<_Tp>::value) 6220b57cec5SDimitry Andric>; 6230b57cec5SDimitry Andric 6240b57cec5SDimitry Andrictemplate<class _Tp> 6250eae32dcSDimitry Andricclass optional; 6260eae32dcSDimitry Andrictemplate <class _Tp> 6270eae32dcSDimitry Andricstruct __is_std_optional : false_type {}; 6280eae32dcSDimitry Andrictemplate <class _Tp> struct __is_std_optional<optional<_Tp>> : true_type {}; 6290eae32dcSDimitry Andric 6300eae32dcSDimitry Andrictemplate <class _Tp> 6310b57cec5SDimitry Andricclass optional 6320b57cec5SDimitry Andric : private __optional_move_assign_base<_Tp> 6330b57cec5SDimitry Andric , private __optional_sfinae_ctor_base_t<_Tp> 6340b57cec5SDimitry Andric , private __optional_sfinae_assign_base_t<_Tp> 6350b57cec5SDimitry Andric{ 6360b57cec5SDimitry Andric using __base = __optional_move_assign_base<_Tp>; 6370b57cec5SDimitry Andricpublic: 6380b57cec5SDimitry Andric using value_type = _Tp; 6390b57cec5SDimitry Andric 6400b57cec5SDimitry Andricprivate: 6410b57cec5SDimitry Andric // Disable the reference extension using this static assert. 642*bdd1243dSDimitry Andric static_assert(!is_same_v<__remove_cvref_t<value_type>, in_place_t>, 6430b57cec5SDimitry Andric "instantiation of optional with in_place_t is ill-formed"); 644*bdd1243dSDimitry Andric static_assert(!is_same_v<__remove_cvref_t<value_type>, nullopt_t>, 6450b57cec5SDimitry Andric "instantiation of optional with nullopt_t is ill-formed"); 6460b57cec5SDimitry Andric static_assert(!is_reference_v<value_type>, 6470b57cec5SDimitry Andric "instantiation of optional with a reference type is ill-formed"); 6480b57cec5SDimitry Andric static_assert(is_destructible_v<value_type>, 6490b57cec5SDimitry Andric "instantiation of optional with a non-destructible type is ill-formed"); 6500b57cec5SDimitry Andric static_assert(!is_array_v<value_type>, 6510b57cec5SDimitry Andric "instantiation of optional with an array type is ill-formed"); 6520b57cec5SDimitry Andric 6530b57cec5SDimitry Andric // LWG2756: conditionally explicit conversion from _Up 6540b57cec5SDimitry Andric struct _CheckOptionalArgsConstructor { 6550b57cec5SDimitry Andric template <class _Up> 6560b57cec5SDimitry Andric static constexpr bool __enable_implicit() { 6570b57cec5SDimitry Andric return is_constructible_v<_Tp, _Up&&> && 6580b57cec5SDimitry Andric is_convertible_v<_Up&&, _Tp>; 6590b57cec5SDimitry Andric } 6600b57cec5SDimitry Andric 6610b57cec5SDimitry Andric template <class _Up> 6620b57cec5SDimitry Andric static constexpr bool __enable_explicit() { 6630b57cec5SDimitry Andric return is_constructible_v<_Tp, _Up&&> && 6640b57cec5SDimitry Andric !is_convertible_v<_Up&&, _Tp>; 6650b57cec5SDimitry Andric } 6660b57cec5SDimitry Andric }; 6670b57cec5SDimitry Andric template <class _Up> 6680b57cec5SDimitry Andric using _CheckOptionalArgsCtor = _If< 669*bdd1243dSDimitry Andric _IsNotSame<__remove_cvref_t<_Up>, in_place_t>::value && 670*bdd1243dSDimitry Andric _IsNotSame<__remove_cvref_t<_Up>, optional>::value, 6710b57cec5SDimitry Andric _CheckOptionalArgsConstructor, 6720b57cec5SDimitry Andric __check_tuple_constructor_fail 6730b57cec5SDimitry Andric >; 6740b57cec5SDimitry Andric template <class _QualUp> 6750b57cec5SDimitry Andric struct _CheckOptionalLikeConstructor { 6760b57cec5SDimitry Andric template <class _Up, class _Opt = optional<_Up>> 6770b57cec5SDimitry Andric using __check_constructible_from_opt = _Or< 6780b57cec5SDimitry Andric is_constructible<_Tp, _Opt&>, 6790b57cec5SDimitry Andric is_constructible<_Tp, _Opt const&>, 6800b57cec5SDimitry Andric is_constructible<_Tp, _Opt&&>, 6810b57cec5SDimitry Andric is_constructible<_Tp, _Opt const&&>, 6820b57cec5SDimitry Andric is_convertible<_Opt&, _Tp>, 6830b57cec5SDimitry Andric is_convertible<_Opt const&, _Tp>, 6840b57cec5SDimitry Andric is_convertible<_Opt&&, _Tp>, 6850b57cec5SDimitry Andric is_convertible<_Opt const&&, _Tp> 6860b57cec5SDimitry Andric >; 6870b57cec5SDimitry Andric template <class _Up, class _Opt = optional<_Up>> 6880b57cec5SDimitry Andric using __check_assignable_from_opt = _Or< 6890b57cec5SDimitry Andric is_assignable<_Tp&, _Opt&>, 6900b57cec5SDimitry Andric is_assignable<_Tp&, _Opt const&>, 6910b57cec5SDimitry Andric is_assignable<_Tp&, _Opt&&>, 6920b57cec5SDimitry Andric is_assignable<_Tp&, _Opt const&&> 6930b57cec5SDimitry Andric >; 6940b57cec5SDimitry Andric template <class _Up, class _QUp = _QualUp> 6950b57cec5SDimitry Andric static constexpr bool __enable_implicit() { 6960b57cec5SDimitry Andric return is_convertible<_QUp, _Tp>::value && 6970b57cec5SDimitry Andric !__check_constructible_from_opt<_Up>::value; 6980b57cec5SDimitry Andric } 6990b57cec5SDimitry Andric template <class _Up, class _QUp = _QualUp> 7000b57cec5SDimitry Andric static constexpr bool __enable_explicit() { 7010b57cec5SDimitry Andric return !is_convertible<_QUp, _Tp>::value && 7020b57cec5SDimitry Andric !__check_constructible_from_opt<_Up>::value; 7030b57cec5SDimitry Andric } 7040b57cec5SDimitry Andric template <class _Up, class _QUp = _QualUp> 7050b57cec5SDimitry Andric static constexpr bool __enable_assign() { 706e8d8bef9SDimitry Andric // Construction and assignability of _QUp to _Tp has already been 7070b57cec5SDimitry Andric // checked. 7080b57cec5SDimitry Andric return !__check_constructible_from_opt<_Up>::value && 7090b57cec5SDimitry Andric !__check_assignable_from_opt<_Up>::value; 7100b57cec5SDimitry Andric } 7110b57cec5SDimitry Andric }; 7120b57cec5SDimitry Andric 7130b57cec5SDimitry Andric template <class _Up, class _QualUp> 7140b57cec5SDimitry Andric using _CheckOptionalLikeCtor = _If< 7150b57cec5SDimitry Andric _And< 7160b57cec5SDimitry Andric _IsNotSame<_Up, _Tp>, 7170b57cec5SDimitry Andric is_constructible<_Tp, _QualUp> 7180b57cec5SDimitry Andric >::value, 7190b57cec5SDimitry Andric _CheckOptionalLikeConstructor<_QualUp>, 7200b57cec5SDimitry Andric __check_tuple_constructor_fail 7210b57cec5SDimitry Andric >; 7220b57cec5SDimitry Andric template <class _Up, class _QualUp> 7230b57cec5SDimitry Andric using _CheckOptionalLikeAssign = _If< 7240b57cec5SDimitry Andric _And< 7250b57cec5SDimitry Andric _IsNotSame<_Up, _Tp>, 7260b57cec5SDimitry Andric is_constructible<_Tp, _QualUp>, 7270b57cec5SDimitry Andric is_assignable<_Tp&, _QualUp> 7280b57cec5SDimitry Andric >::value, 7290b57cec5SDimitry Andric _CheckOptionalLikeConstructor<_QualUp>, 7300b57cec5SDimitry Andric __check_tuple_constructor_fail 7310b57cec5SDimitry Andric >; 7320eae32dcSDimitry Andric 7330b57cec5SDimitry Andricpublic: 7340b57cec5SDimitry Andric 7350b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY constexpr optional() noexcept {} 7360b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY constexpr optional(const optional&) = default; 7370b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY constexpr optional(optional&&) = default; 7380b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY constexpr optional(nullopt_t) noexcept {} 7390b57cec5SDimitry Andric 740349cc55cSDimitry Andric template <class _InPlaceT, class... _Args, class = enable_if_t< 7410b57cec5SDimitry Andric _And< 7420b57cec5SDimitry Andric _IsSame<_InPlaceT, in_place_t>, 7430b57cec5SDimitry Andric is_constructible<value_type, _Args...> 7440b57cec5SDimitry Andric >::value 7450b57cec5SDimitry Andric > 7460b57cec5SDimitry Andric > 7470b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY 7480b57cec5SDimitry Andric constexpr explicit optional(_InPlaceT, _Args&&... __args) 7490b57cec5SDimitry Andric : __base(in_place, _VSTD::forward<_Args>(__args)...) {} 7500b57cec5SDimitry Andric 751349cc55cSDimitry Andric template <class _Up, class... _Args, class = enable_if_t< 7520b57cec5SDimitry Andric is_constructible_v<value_type, initializer_list<_Up>&, _Args...>> 7530b57cec5SDimitry Andric > 7540b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY 7550b57cec5SDimitry Andric constexpr explicit optional(in_place_t, initializer_list<_Up> __il, _Args&&... __args) 7560b57cec5SDimitry Andric : __base(in_place, __il, _VSTD::forward<_Args>(__args)...) {} 7570b57cec5SDimitry Andric 758349cc55cSDimitry Andric template <class _Up = value_type, enable_if_t< 7590b57cec5SDimitry Andric _CheckOptionalArgsCtor<_Up>::template __enable_implicit<_Up>() 7600b57cec5SDimitry Andric , int> = 0> 7610b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY 7620b57cec5SDimitry Andric constexpr optional(_Up&& __v) 7630b57cec5SDimitry Andric : __base(in_place, _VSTD::forward<_Up>(__v)) {} 7640b57cec5SDimitry Andric 765349cc55cSDimitry Andric template <class _Up, enable_if_t< 7660b57cec5SDimitry Andric _CheckOptionalArgsCtor<_Up>::template __enable_explicit<_Up>() 7670b57cec5SDimitry Andric , int> = 0> 7680b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY 7690b57cec5SDimitry Andric constexpr explicit optional(_Up&& __v) 7700b57cec5SDimitry Andric : __base(in_place, _VSTD::forward<_Up>(__v)) {} 7710b57cec5SDimitry Andric 7720b57cec5SDimitry Andric // LWG2756: conditionally explicit conversion from const optional<_Up>& 773349cc55cSDimitry Andric template <class _Up, enable_if_t< 7740b57cec5SDimitry Andric _CheckOptionalLikeCtor<_Up, _Up const&>::template __enable_implicit<_Up>() 7750b57cec5SDimitry Andric , int> = 0> 7760b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY 777*bdd1243dSDimitry Andric _LIBCPP_CONSTEXPR_SINCE_CXX20 optional(const optional<_Up>& __v) 7780b57cec5SDimitry Andric { 7790b57cec5SDimitry Andric this->__construct_from(__v); 7800b57cec5SDimitry Andric } 781349cc55cSDimitry Andric template <class _Up, enable_if_t< 7820b57cec5SDimitry Andric _CheckOptionalLikeCtor<_Up, _Up const&>::template __enable_explicit<_Up>() 7830b57cec5SDimitry Andric , int> = 0> 7840b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY 785*bdd1243dSDimitry Andric _LIBCPP_CONSTEXPR_SINCE_CXX20 explicit optional(const optional<_Up>& __v) 7860b57cec5SDimitry Andric { 7870b57cec5SDimitry Andric this->__construct_from(__v); 7880b57cec5SDimitry Andric } 7890b57cec5SDimitry Andric 7900b57cec5SDimitry Andric // LWG2756: conditionally explicit conversion from optional<_Up>&& 791349cc55cSDimitry Andric template <class _Up, enable_if_t< 7920b57cec5SDimitry Andric _CheckOptionalLikeCtor<_Up, _Up &&>::template __enable_implicit<_Up>() 7930b57cec5SDimitry Andric , int> = 0> 7940b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY 795*bdd1243dSDimitry Andric _LIBCPP_CONSTEXPR_SINCE_CXX20 optional(optional<_Up>&& __v) 7960b57cec5SDimitry Andric { 7970b57cec5SDimitry Andric this->__construct_from(_VSTD::move(__v)); 7980b57cec5SDimitry Andric } 799349cc55cSDimitry Andric template <class _Up, enable_if_t< 8000b57cec5SDimitry Andric _CheckOptionalLikeCtor<_Up, _Up &&>::template __enable_explicit<_Up>() 8010b57cec5SDimitry Andric , int> = 0> 8020b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY 803*bdd1243dSDimitry Andric _LIBCPP_CONSTEXPR_SINCE_CXX20 explicit optional(optional<_Up>&& __v) 8040b57cec5SDimitry Andric { 8050b57cec5SDimitry Andric this->__construct_from(_VSTD::move(__v)); 8060b57cec5SDimitry Andric } 8070b57cec5SDimitry Andric 8080eae32dcSDimitry Andric#if _LIBCPP_STD_VER > 20 8090eae32dcSDimitry Andric template<class _Fp, class... _Args> 8100eae32dcSDimitry Andric _LIBCPP_HIDE_FROM_ABI 8110eae32dcSDimitry Andric constexpr explicit optional(__optional_construct_from_invoke_tag, _Fp&& __f, _Args&&... __args) 8120eae32dcSDimitry Andric : __base(__optional_construct_from_invoke_tag{}, _VSTD::forward<_Fp>(__f), _VSTD::forward<_Args>(__args)...) { 8130eae32dcSDimitry Andric } 8140eae32dcSDimitry Andric#endif 8150eae32dcSDimitry Andric 8160b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY 817*bdd1243dSDimitry Andric _LIBCPP_CONSTEXPR_SINCE_CXX20 optional& operator=(nullopt_t) noexcept 8180b57cec5SDimitry Andric { 8190b57cec5SDimitry Andric reset(); 8200b57cec5SDimitry Andric return *this; 8210b57cec5SDimitry Andric } 8220b57cec5SDimitry Andric 823*bdd1243dSDimitry Andric constexpr optional& operator=(const optional&) = default; 824*bdd1243dSDimitry Andric constexpr optional& operator=(optional&&) = default; 8250b57cec5SDimitry Andric 8260b57cec5SDimitry Andric // LWG2756 8270b57cec5SDimitry Andric template <class _Up = value_type, 828349cc55cSDimitry Andric class = enable_if_t< 8290b57cec5SDimitry Andric _And< 830*bdd1243dSDimitry Andric _IsNotSame<__remove_cvref_t<_Up>, optional>, 8310b57cec5SDimitry Andric _Or< 832*bdd1243dSDimitry Andric _IsNotSame<__remove_cvref_t<_Up>, value_type>, 8330b57cec5SDimitry Andric _Not<is_scalar<value_type>> 8340b57cec5SDimitry Andric >, 8350b57cec5SDimitry Andric is_constructible<value_type, _Up>, 8360b57cec5SDimitry Andric is_assignable<value_type&, _Up> 8370b57cec5SDimitry Andric >::value> 8380b57cec5SDimitry Andric > 8390b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY 840*bdd1243dSDimitry Andric _LIBCPP_CONSTEXPR_SINCE_CXX20 optional& 8410b57cec5SDimitry Andric operator=(_Up&& __v) 8420b57cec5SDimitry Andric { 8430b57cec5SDimitry Andric if (this->has_value()) 8440b57cec5SDimitry Andric this->__get() = _VSTD::forward<_Up>(__v); 8450b57cec5SDimitry Andric else 8460b57cec5SDimitry Andric this->__construct(_VSTD::forward<_Up>(__v)); 8470b57cec5SDimitry Andric return *this; 8480b57cec5SDimitry Andric } 8490b57cec5SDimitry Andric 8500b57cec5SDimitry Andric // LWG2756 851349cc55cSDimitry Andric template <class _Up, enable_if_t< 8520b57cec5SDimitry Andric _CheckOptionalLikeAssign<_Up, _Up const&>::template __enable_assign<_Up>() 8530b57cec5SDimitry Andric , int> = 0> 8540b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY 855*bdd1243dSDimitry Andric _LIBCPP_CONSTEXPR_SINCE_CXX20 optional& 8560b57cec5SDimitry Andric operator=(const optional<_Up>& __v) 8570b57cec5SDimitry Andric { 8580b57cec5SDimitry Andric this->__assign_from(__v); 8590b57cec5SDimitry Andric return *this; 8600b57cec5SDimitry Andric } 8610b57cec5SDimitry Andric 8620b57cec5SDimitry Andric // LWG2756 863349cc55cSDimitry Andric template <class _Up, enable_if_t< 8640b57cec5SDimitry Andric _CheckOptionalLikeCtor<_Up, _Up &&>::template __enable_assign<_Up>() 8650b57cec5SDimitry Andric , int> = 0> 8660b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY 867*bdd1243dSDimitry Andric _LIBCPP_CONSTEXPR_SINCE_CXX20 optional& 8680b57cec5SDimitry Andric operator=(optional<_Up>&& __v) 8690b57cec5SDimitry Andric { 8700b57cec5SDimitry Andric this->__assign_from(_VSTD::move(__v)); 8710b57cec5SDimitry Andric return *this; 8720b57cec5SDimitry Andric } 8730b57cec5SDimitry Andric 8740b57cec5SDimitry Andric template <class... _Args, 875349cc55cSDimitry Andric class = enable_if_t 8760b57cec5SDimitry Andric < 8770b57cec5SDimitry Andric is_constructible_v<value_type, _Args...> 8780b57cec5SDimitry Andric > 8790b57cec5SDimitry Andric > 8800b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY 881*bdd1243dSDimitry Andric _LIBCPP_CONSTEXPR_SINCE_CXX20 _Tp & 8820b57cec5SDimitry Andric emplace(_Args&&... __args) 8830b57cec5SDimitry Andric { 8840b57cec5SDimitry Andric reset(); 8850b57cec5SDimitry Andric this->__construct(_VSTD::forward<_Args>(__args)...); 8860b57cec5SDimitry Andric return this->__get(); 8870b57cec5SDimitry Andric } 8880b57cec5SDimitry Andric 8890b57cec5SDimitry Andric template <class _Up, class... _Args, 890349cc55cSDimitry Andric class = enable_if_t 8910b57cec5SDimitry Andric < 8920b57cec5SDimitry Andric is_constructible_v<value_type, initializer_list<_Up>&, _Args...> 8930b57cec5SDimitry Andric > 8940b57cec5SDimitry Andric > 8950b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY 896*bdd1243dSDimitry Andric _LIBCPP_CONSTEXPR_SINCE_CXX20 _Tp & 8970b57cec5SDimitry Andric emplace(initializer_list<_Up> __il, _Args&&... __args) 8980b57cec5SDimitry Andric { 8990b57cec5SDimitry Andric reset(); 9000b57cec5SDimitry Andric this->__construct(__il, _VSTD::forward<_Args>(__args)...); 9010b57cec5SDimitry Andric return this->__get(); 9020b57cec5SDimitry Andric } 9030b57cec5SDimitry Andric 9040b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY 905*bdd1243dSDimitry Andric _LIBCPP_CONSTEXPR_SINCE_CXX20 void swap(optional& __opt) 9060b57cec5SDimitry Andric noexcept(is_nothrow_move_constructible_v<value_type> && 9070b57cec5SDimitry Andric is_nothrow_swappable_v<value_type>) 9080b57cec5SDimitry Andric { 9090b57cec5SDimitry Andric if (this->has_value() == __opt.has_value()) 9100b57cec5SDimitry Andric { 9110b57cec5SDimitry Andric using _VSTD::swap; 9120b57cec5SDimitry Andric if (this->has_value()) 9130b57cec5SDimitry Andric swap(this->__get(), __opt.__get()); 9140b57cec5SDimitry Andric } 9150b57cec5SDimitry Andric else 9160b57cec5SDimitry Andric { 9170b57cec5SDimitry Andric if (this->has_value()) 9180b57cec5SDimitry Andric { 9190b57cec5SDimitry Andric __opt.__construct(_VSTD::move(this->__get())); 9200b57cec5SDimitry Andric reset(); 9210b57cec5SDimitry Andric } 9220b57cec5SDimitry Andric else 9230b57cec5SDimitry Andric { 9240b57cec5SDimitry Andric this->__construct(_VSTD::move(__opt.__get())); 9250b57cec5SDimitry Andric __opt.reset(); 9260b57cec5SDimitry Andric } 9270b57cec5SDimitry Andric } 9280b57cec5SDimitry Andric } 9290b57cec5SDimitry Andric 9300b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY 9310b57cec5SDimitry Andric constexpr 9320b57cec5SDimitry Andric add_pointer_t<value_type const> 9330b57cec5SDimitry Andric operator->() const 9340b57cec5SDimitry Andric { 935fe6060f1SDimitry Andric _LIBCPP_ASSERT(this->has_value(), "optional operator-> called on a disengaged value"); 9360b57cec5SDimitry Andric return _VSTD::addressof(this->__get()); 9370b57cec5SDimitry Andric } 9380b57cec5SDimitry Andric 9390b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY 9400b57cec5SDimitry Andric constexpr 9410b57cec5SDimitry Andric add_pointer_t<value_type> 9420b57cec5SDimitry Andric operator->() 9430b57cec5SDimitry Andric { 944fe6060f1SDimitry Andric _LIBCPP_ASSERT(this->has_value(), "optional operator-> called on a disengaged value"); 9450b57cec5SDimitry Andric return _VSTD::addressof(this->__get()); 9460b57cec5SDimitry Andric } 9470b57cec5SDimitry Andric 9480b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY 9490b57cec5SDimitry Andric constexpr 9500b57cec5SDimitry Andric const value_type& 951fe6060f1SDimitry Andric operator*() const& noexcept 9520b57cec5SDimitry Andric { 953fe6060f1SDimitry Andric _LIBCPP_ASSERT(this->has_value(), "optional operator* called on a disengaged value"); 9540b57cec5SDimitry Andric return this->__get(); 9550b57cec5SDimitry Andric } 9560b57cec5SDimitry Andric 9570b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY 9580b57cec5SDimitry Andric constexpr 9590b57cec5SDimitry Andric value_type& 960fe6060f1SDimitry Andric operator*() & noexcept 9610b57cec5SDimitry Andric { 962fe6060f1SDimitry Andric _LIBCPP_ASSERT(this->has_value(), "optional operator* called on a disengaged value"); 9630b57cec5SDimitry Andric return this->__get(); 9640b57cec5SDimitry Andric } 9650b57cec5SDimitry Andric 9660b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY 9670b57cec5SDimitry Andric constexpr 9680b57cec5SDimitry Andric value_type&& 969fe6060f1SDimitry Andric operator*() && noexcept 9700b57cec5SDimitry Andric { 971fe6060f1SDimitry Andric _LIBCPP_ASSERT(this->has_value(), "optional operator* called on a disengaged value"); 9720b57cec5SDimitry Andric return _VSTD::move(this->__get()); 9730b57cec5SDimitry Andric } 9740b57cec5SDimitry Andric 9750b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY 9760b57cec5SDimitry Andric constexpr 9770b57cec5SDimitry Andric const value_type&& 978fe6060f1SDimitry Andric operator*() const&& noexcept 9790b57cec5SDimitry Andric { 980fe6060f1SDimitry Andric _LIBCPP_ASSERT(this->has_value(), "optional operator* called on a disengaged value"); 9810b57cec5SDimitry Andric return _VSTD::move(this->__get()); 9820b57cec5SDimitry Andric } 9830b57cec5SDimitry Andric 9840b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY 9850b57cec5SDimitry Andric constexpr explicit operator bool() const noexcept { return has_value(); } 9860b57cec5SDimitry Andric 9870b57cec5SDimitry Andric using __base::has_value; 9880b57cec5SDimitry Andric using __base::__get; 9890b57cec5SDimitry Andric 9900b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY 9910b57cec5SDimitry Andric _LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS 9920b57cec5SDimitry Andric constexpr value_type const& value() const& 9930b57cec5SDimitry Andric { 9940b57cec5SDimitry Andric if (!this->has_value()) 9950b57cec5SDimitry Andric __throw_bad_optional_access(); 9960b57cec5SDimitry Andric return this->__get(); 9970b57cec5SDimitry Andric } 9980b57cec5SDimitry Andric 9990b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY 10000b57cec5SDimitry Andric _LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS 10010b57cec5SDimitry Andric constexpr value_type& value() & 10020b57cec5SDimitry Andric { 10030b57cec5SDimitry Andric if (!this->has_value()) 10040b57cec5SDimitry Andric __throw_bad_optional_access(); 10050b57cec5SDimitry Andric return this->__get(); 10060b57cec5SDimitry Andric } 10070b57cec5SDimitry Andric 10080b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY 10090b57cec5SDimitry Andric _LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS 10100b57cec5SDimitry Andric constexpr value_type&& value() && 10110b57cec5SDimitry Andric { 10120b57cec5SDimitry Andric if (!this->has_value()) 10130b57cec5SDimitry Andric __throw_bad_optional_access(); 10140b57cec5SDimitry Andric return _VSTD::move(this->__get()); 10150b57cec5SDimitry Andric } 10160b57cec5SDimitry Andric 10170b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY 10180b57cec5SDimitry Andric _LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS 10190b57cec5SDimitry Andric constexpr value_type const&& value() const&& 10200b57cec5SDimitry Andric { 10210b57cec5SDimitry Andric if (!this->has_value()) 10220b57cec5SDimitry Andric __throw_bad_optional_access(); 10230b57cec5SDimitry Andric return _VSTD::move(this->__get()); 10240b57cec5SDimitry Andric } 10250b57cec5SDimitry Andric 10260b57cec5SDimitry Andric template <class _Up> 10270b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY 10280b57cec5SDimitry Andric constexpr value_type value_or(_Up&& __v) const& 10290b57cec5SDimitry Andric { 10300b57cec5SDimitry Andric static_assert(is_copy_constructible_v<value_type>, 10310b57cec5SDimitry Andric "optional<T>::value_or: T must be copy constructible"); 10320b57cec5SDimitry Andric static_assert(is_convertible_v<_Up, value_type>, 10330b57cec5SDimitry Andric "optional<T>::value_or: U must be convertible to T"); 10340b57cec5SDimitry Andric return this->has_value() ? this->__get() : 10350b57cec5SDimitry Andric static_cast<value_type>(_VSTD::forward<_Up>(__v)); 10360b57cec5SDimitry Andric } 10370b57cec5SDimitry Andric 10380b57cec5SDimitry Andric template <class _Up> 10390b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY 10400b57cec5SDimitry Andric constexpr value_type value_or(_Up&& __v) && 10410b57cec5SDimitry Andric { 10420b57cec5SDimitry Andric static_assert(is_move_constructible_v<value_type>, 10430b57cec5SDimitry Andric "optional<T>::value_or: T must be move constructible"); 10440b57cec5SDimitry Andric static_assert(is_convertible_v<_Up, value_type>, 10450b57cec5SDimitry Andric "optional<T>::value_or: U must be convertible to T"); 10460b57cec5SDimitry Andric return this->has_value() ? _VSTD::move(this->__get()) : 10470b57cec5SDimitry Andric static_cast<value_type>(_VSTD::forward<_Up>(__v)); 10480b57cec5SDimitry Andric } 10490b57cec5SDimitry Andric 10500eae32dcSDimitry Andric#if _LIBCPP_STD_VER > 20 10510eae32dcSDimitry Andric template<class _Func> 105281ad6265SDimitry Andric _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS 10530eae32dcSDimitry Andric constexpr auto and_then(_Func&& __f) & { 10540eae32dcSDimitry Andric using _Up = invoke_result_t<_Func, value_type&>; 10550eae32dcSDimitry Andric static_assert(__is_std_optional<remove_cvref_t<_Up>>::value, 10560eae32dcSDimitry Andric "Result of f(value()) must be a specialization of std::optional"); 10570eae32dcSDimitry Andric if (*this) 10580eae32dcSDimitry Andric return _VSTD::invoke(_VSTD::forward<_Func>(__f), value()); 10590eae32dcSDimitry Andric return remove_cvref_t<_Up>(); 10600eae32dcSDimitry Andric } 10610eae32dcSDimitry Andric 10620eae32dcSDimitry Andric template<class _Func> 106381ad6265SDimitry Andric _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS 10640eae32dcSDimitry Andric constexpr auto and_then(_Func&& __f) const& { 10650eae32dcSDimitry Andric using _Up = invoke_result_t<_Func, const value_type&>; 10660eae32dcSDimitry Andric static_assert(__is_std_optional<remove_cvref_t<_Up>>::value, 10670eae32dcSDimitry Andric "Result of f(value()) must be a specialization of std::optional"); 10680eae32dcSDimitry Andric if (*this) 10690eae32dcSDimitry Andric return _VSTD::invoke(_VSTD::forward<_Func>(__f), value()); 10700eae32dcSDimitry Andric return remove_cvref_t<_Up>(); 10710eae32dcSDimitry Andric } 10720eae32dcSDimitry Andric 10730eae32dcSDimitry Andric template<class _Func> 107481ad6265SDimitry Andric _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS 10750eae32dcSDimitry Andric constexpr auto and_then(_Func&& __f) && { 10760eae32dcSDimitry Andric using _Up = invoke_result_t<_Func, value_type&&>; 10770eae32dcSDimitry Andric static_assert(__is_std_optional<remove_cvref_t<_Up>>::value, 10780eae32dcSDimitry Andric "Result of f(std::move(value())) must be a specialization of std::optional"); 10790eae32dcSDimitry Andric if (*this) 10800eae32dcSDimitry Andric return _VSTD::invoke(_VSTD::forward<_Func>(__f), _VSTD::move(value())); 10810eae32dcSDimitry Andric return remove_cvref_t<_Up>(); 10820eae32dcSDimitry Andric } 10830eae32dcSDimitry Andric 10840eae32dcSDimitry Andric template<class _Func> 10850eae32dcSDimitry Andric _LIBCPP_HIDE_FROM_ABI 10860eae32dcSDimitry Andric constexpr auto and_then(_Func&& __f) const&& { 10870eae32dcSDimitry Andric using _Up = invoke_result_t<_Func, const value_type&&>; 10880eae32dcSDimitry Andric static_assert(__is_std_optional<remove_cvref_t<_Up>>::value, 10890eae32dcSDimitry Andric "Result of f(std::move(value())) must be a specialization of std::optional"); 10900eae32dcSDimitry Andric if (*this) 10910eae32dcSDimitry Andric return _VSTD::invoke(_VSTD::forward<_Func>(__f), _VSTD::move(value())); 10920eae32dcSDimitry Andric return remove_cvref_t<_Up>(); 10930eae32dcSDimitry Andric } 10940eae32dcSDimitry Andric 10950eae32dcSDimitry Andric template<class _Func> 109681ad6265SDimitry Andric _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS 10970eae32dcSDimitry Andric constexpr auto transform(_Func&& __f) & { 10980eae32dcSDimitry Andric using _Up = remove_cv_t<invoke_result_t<_Func, value_type&>>; 10990eae32dcSDimitry Andric static_assert(!is_array_v<_Up>, "Result of f(value()) should not be an Array"); 11000eae32dcSDimitry Andric static_assert(!is_same_v<_Up, in_place_t>, 11010eae32dcSDimitry Andric "Result of f(value()) should not be std::in_place_t"); 11020eae32dcSDimitry Andric static_assert(!is_same_v<_Up, nullopt_t>, 11030eae32dcSDimitry Andric "Result of f(value()) should not be std::nullopt_t"); 11040eae32dcSDimitry Andric static_assert(is_object_v<_Up>, "Result of f(value()) should be an object type"); 11050eae32dcSDimitry Andric if (*this) 11060eae32dcSDimitry Andric return optional<_Up>(__optional_construct_from_invoke_tag{}, _VSTD::forward<_Func>(__f), value()); 11070eae32dcSDimitry Andric return optional<_Up>(); 11080eae32dcSDimitry Andric } 11090eae32dcSDimitry Andric 11100eae32dcSDimitry Andric template<class _Func> 111181ad6265SDimitry Andric _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS 11120eae32dcSDimitry Andric constexpr auto transform(_Func&& __f) const& { 11130eae32dcSDimitry Andric using _Up = remove_cv_t<invoke_result_t<_Func, const value_type&>>; 11140eae32dcSDimitry Andric static_assert(!is_array_v<_Up>, "Result of f(value()) should not be an Array"); 11150eae32dcSDimitry Andric static_assert(!is_same_v<_Up, in_place_t>, 11160eae32dcSDimitry Andric "Result of f(value()) should not be std::in_place_t"); 11170eae32dcSDimitry Andric static_assert(!is_same_v<_Up, nullopt_t>, 11180eae32dcSDimitry Andric "Result of f(value()) should not be std::nullopt_t"); 11190eae32dcSDimitry Andric static_assert(is_object_v<_Up>, "Result of f(value()) should be an object type"); 11200eae32dcSDimitry Andric if (*this) 11210eae32dcSDimitry Andric return optional<_Up>(__optional_construct_from_invoke_tag{}, _VSTD::forward<_Func>(__f), value()); 11220eae32dcSDimitry Andric return optional<_Up>(); 11230eae32dcSDimitry Andric } 11240eae32dcSDimitry Andric 11250eae32dcSDimitry Andric template<class _Func> 112681ad6265SDimitry Andric _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS 11270eae32dcSDimitry Andric constexpr auto transform(_Func&& __f) && { 11280eae32dcSDimitry Andric using _Up = remove_cv_t<invoke_result_t<_Func, value_type&&>>; 11290eae32dcSDimitry Andric static_assert(!is_array_v<_Up>, "Result of f(std::move(value())) should not be an Array"); 11300eae32dcSDimitry Andric static_assert(!is_same_v<_Up, in_place_t>, 11310eae32dcSDimitry Andric "Result of f(std::move(value())) should not be std::in_place_t"); 11320eae32dcSDimitry Andric static_assert(!is_same_v<_Up, nullopt_t>, 11330eae32dcSDimitry Andric "Result of f(std::move(value())) should not be std::nullopt_t"); 11340eae32dcSDimitry Andric static_assert(is_object_v<_Up>, "Result of f(std::move(value())) should be an object type"); 11350eae32dcSDimitry Andric if (*this) 11360eae32dcSDimitry Andric return optional<_Up>(__optional_construct_from_invoke_tag{}, _VSTD::forward<_Func>(__f), _VSTD::move(value())); 11370eae32dcSDimitry Andric return optional<_Up>(); 11380eae32dcSDimitry Andric } 11390eae32dcSDimitry Andric 11400eae32dcSDimitry Andric template<class _Func> 114181ad6265SDimitry Andric _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS 11420eae32dcSDimitry Andric constexpr auto transform(_Func&& __f) const&& { 11430eae32dcSDimitry Andric using _Up = remove_cvref_t<invoke_result_t<_Func, const value_type&&>>; 11440eae32dcSDimitry Andric static_assert(!is_array_v<_Up>, "Result of f(std::move(value())) should not be an Array"); 11450eae32dcSDimitry Andric static_assert(!is_same_v<_Up, in_place_t>, 11460eae32dcSDimitry Andric "Result of f(std::move(value())) should not be std::in_place_t"); 11470eae32dcSDimitry Andric static_assert(!is_same_v<_Up, nullopt_t>, 11480eae32dcSDimitry Andric "Result of f(std::move(value())) should not be std::nullopt_t"); 11490eae32dcSDimitry Andric static_assert(is_object_v<_Up>, "Result of f(std::move(value())) should be an object type"); 11500eae32dcSDimitry Andric if (*this) 11510eae32dcSDimitry Andric return optional<_Up>(__optional_construct_from_invoke_tag{}, _VSTD::forward<_Func>(__f), _VSTD::move(value())); 11520eae32dcSDimitry Andric return optional<_Up>(); 11530eae32dcSDimitry Andric } 11540eae32dcSDimitry Andric 11550eae32dcSDimitry Andric template<invocable _Func> 11560eae32dcSDimitry Andric _LIBCPP_HIDE_FROM_ABI 11570eae32dcSDimitry Andric constexpr optional or_else(_Func&& __f) const& requires is_copy_constructible_v<value_type> { 11580eae32dcSDimitry Andric static_assert(is_same_v<remove_cvref_t<invoke_result_t<_Func>>, optional>, 11590eae32dcSDimitry Andric "Result of f() should be the same type as this optional"); 11600eae32dcSDimitry Andric if (*this) 11610eae32dcSDimitry Andric return *this; 11620eae32dcSDimitry Andric return _VSTD::forward<_Func>(__f)(); 11630eae32dcSDimitry Andric } 11640eae32dcSDimitry Andric 11650eae32dcSDimitry Andric template<invocable _Func> 11660eae32dcSDimitry Andric _LIBCPP_HIDE_FROM_ABI 11670eae32dcSDimitry Andric constexpr optional or_else(_Func&& __f) && requires is_move_constructible_v<value_type> { 11680eae32dcSDimitry Andric static_assert(is_same_v<remove_cvref_t<invoke_result_t<_Func>>, optional>, 11690eae32dcSDimitry Andric "Result of f() should be the same type as this optional"); 11700eae32dcSDimitry Andric if (*this) 11710eae32dcSDimitry Andric return _VSTD::move(*this); 11720eae32dcSDimitry Andric return _VSTD::forward<_Func>(__f)(); 11730eae32dcSDimitry Andric } 11740eae32dcSDimitry Andric#endif // _LIBCPP_STD_VER > 20 11750eae32dcSDimitry Andric 11760b57cec5SDimitry Andric using __base::reset; 11770b57cec5SDimitry Andric}; 11780b57cec5SDimitry Andric 1179349cc55cSDimitry Andric#if _LIBCPP_STD_VER >= 17 118004eeddc0SDimitry Andrictemplate<class _Tp> 118104eeddc0SDimitry Andric optional(_Tp) -> optional<_Tp>; 11820b57cec5SDimitry Andric#endif 11830b57cec5SDimitry Andric 11840b57cec5SDimitry Andric// Comparisons between optionals 11850b57cec5SDimitry Andrictemplate <class _Tp, class _Up> 11860b57cec5SDimitry Andric_LIBCPP_INLINE_VISIBILITY constexpr 1187349cc55cSDimitry Andricenable_if_t< 1188*bdd1243dSDimitry Andric is_convertible_v<decltype(std::declval<const _Tp&>() == 1189*bdd1243dSDimitry Andric std::declval<const _Up&>()), bool>, 11900b57cec5SDimitry Andric bool 11910b57cec5SDimitry Andric> 11920b57cec5SDimitry Andricoperator==(const optional<_Tp>& __x, const optional<_Up>& __y) 11930b57cec5SDimitry Andric{ 11940b57cec5SDimitry Andric if (static_cast<bool>(__x) != static_cast<bool>(__y)) 11950b57cec5SDimitry Andric return false; 11960b57cec5SDimitry Andric if (!static_cast<bool>(__x)) 11970b57cec5SDimitry Andric return true; 11980b57cec5SDimitry Andric return *__x == *__y; 11990b57cec5SDimitry Andric} 12000b57cec5SDimitry Andric 12010b57cec5SDimitry Andrictemplate <class _Tp, class _Up> 12020b57cec5SDimitry Andric_LIBCPP_INLINE_VISIBILITY constexpr 1203349cc55cSDimitry Andricenable_if_t< 1204*bdd1243dSDimitry Andric is_convertible_v<decltype(std::declval<const _Tp&>() != 1205*bdd1243dSDimitry Andric std::declval<const _Up&>()), bool>, 12060b57cec5SDimitry Andric bool 12070b57cec5SDimitry Andric> 12080b57cec5SDimitry Andricoperator!=(const optional<_Tp>& __x, const optional<_Up>& __y) 12090b57cec5SDimitry Andric{ 12100b57cec5SDimitry Andric if (static_cast<bool>(__x) != static_cast<bool>(__y)) 12110b57cec5SDimitry Andric return true; 12120b57cec5SDimitry Andric if (!static_cast<bool>(__x)) 12130b57cec5SDimitry Andric return false; 12140b57cec5SDimitry Andric return *__x != *__y; 12150b57cec5SDimitry Andric} 12160b57cec5SDimitry Andric 12170b57cec5SDimitry Andrictemplate <class _Tp, class _Up> 12180b57cec5SDimitry Andric_LIBCPP_INLINE_VISIBILITY constexpr 1219349cc55cSDimitry Andricenable_if_t< 1220*bdd1243dSDimitry Andric is_convertible_v<decltype(std::declval<const _Tp&>() < 1221*bdd1243dSDimitry Andric std::declval<const _Up&>()), bool>, 12220b57cec5SDimitry Andric bool 12230b57cec5SDimitry Andric> 12240b57cec5SDimitry Andricoperator<(const optional<_Tp>& __x, const optional<_Up>& __y) 12250b57cec5SDimitry Andric{ 12260b57cec5SDimitry Andric if (!static_cast<bool>(__y)) 12270b57cec5SDimitry Andric return false; 12280b57cec5SDimitry Andric if (!static_cast<bool>(__x)) 12290b57cec5SDimitry Andric return true; 12300b57cec5SDimitry Andric return *__x < *__y; 12310b57cec5SDimitry Andric} 12320b57cec5SDimitry Andric 12330b57cec5SDimitry Andrictemplate <class _Tp, class _Up> 12340b57cec5SDimitry Andric_LIBCPP_INLINE_VISIBILITY constexpr 1235349cc55cSDimitry Andricenable_if_t< 1236*bdd1243dSDimitry Andric is_convertible_v<decltype(std::declval<const _Tp&>() > 1237*bdd1243dSDimitry Andric std::declval<const _Up&>()), bool>, 12380b57cec5SDimitry Andric bool 12390b57cec5SDimitry Andric> 12400b57cec5SDimitry Andricoperator>(const optional<_Tp>& __x, const optional<_Up>& __y) 12410b57cec5SDimitry Andric{ 12420b57cec5SDimitry Andric if (!static_cast<bool>(__x)) 12430b57cec5SDimitry Andric return false; 12440b57cec5SDimitry Andric if (!static_cast<bool>(__y)) 12450b57cec5SDimitry Andric return true; 12460b57cec5SDimitry Andric return *__x > *__y; 12470b57cec5SDimitry Andric} 12480b57cec5SDimitry Andric 12490b57cec5SDimitry Andrictemplate <class _Tp, class _Up> 12500b57cec5SDimitry Andric_LIBCPP_INLINE_VISIBILITY constexpr 1251349cc55cSDimitry Andricenable_if_t< 1252*bdd1243dSDimitry Andric is_convertible_v<decltype(std::declval<const _Tp&>() <= 1253*bdd1243dSDimitry Andric std::declval<const _Up&>()), bool>, 12540b57cec5SDimitry Andric bool 12550b57cec5SDimitry Andric> 12560b57cec5SDimitry Andricoperator<=(const optional<_Tp>& __x, const optional<_Up>& __y) 12570b57cec5SDimitry Andric{ 12580b57cec5SDimitry Andric if (!static_cast<bool>(__x)) 12590b57cec5SDimitry Andric return true; 12600b57cec5SDimitry Andric if (!static_cast<bool>(__y)) 12610b57cec5SDimitry Andric return false; 12620b57cec5SDimitry Andric return *__x <= *__y; 12630b57cec5SDimitry Andric} 12640b57cec5SDimitry Andric 12650b57cec5SDimitry Andrictemplate <class _Tp, class _Up> 12660b57cec5SDimitry Andric_LIBCPP_INLINE_VISIBILITY constexpr 1267349cc55cSDimitry Andricenable_if_t< 1268*bdd1243dSDimitry Andric is_convertible_v<decltype(std::declval<const _Tp&>() >= 1269*bdd1243dSDimitry Andric std::declval<const _Up&>()), bool>, 12700b57cec5SDimitry Andric bool 12710b57cec5SDimitry Andric> 12720b57cec5SDimitry Andricoperator>=(const optional<_Tp>& __x, const optional<_Up>& __y) 12730b57cec5SDimitry Andric{ 12740b57cec5SDimitry Andric if (!static_cast<bool>(__y)) 12750b57cec5SDimitry Andric return true; 12760b57cec5SDimitry Andric if (!static_cast<bool>(__x)) 12770b57cec5SDimitry Andric return false; 12780b57cec5SDimitry Andric return *__x >= *__y; 12790b57cec5SDimitry Andric} 12800b57cec5SDimitry Andric 12810b57cec5SDimitry Andric// Comparisons with nullopt 12820b57cec5SDimitry Andrictemplate <class _Tp> 12830b57cec5SDimitry Andric_LIBCPP_INLINE_VISIBILITY constexpr 12840b57cec5SDimitry Andricbool 12850b57cec5SDimitry Andricoperator==(const optional<_Tp>& __x, nullopt_t) noexcept 12860b57cec5SDimitry Andric{ 12870b57cec5SDimitry Andric return !static_cast<bool>(__x); 12880b57cec5SDimitry Andric} 12890b57cec5SDimitry Andric 12900b57cec5SDimitry Andrictemplate <class _Tp> 12910b57cec5SDimitry Andric_LIBCPP_INLINE_VISIBILITY constexpr 12920b57cec5SDimitry Andricbool 12930b57cec5SDimitry Andricoperator==(nullopt_t, const optional<_Tp>& __x) noexcept 12940b57cec5SDimitry Andric{ 12950b57cec5SDimitry Andric return !static_cast<bool>(__x); 12960b57cec5SDimitry Andric} 12970b57cec5SDimitry Andric 12980b57cec5SDimitry Andrictemplate <class _Tp> 12990b57cec5SDimitry Andric_LIBCPP_INLINE_VISIBILITY constexpr 13000b57cec5SDimitry Andricbool 13010b57cec5SDimitry Andricoperator!=(const optional<_Tp>& __x, nullopt_t) noexcept 13020b57cec5SDimitry Andric{ 13030b57cec5SDimitry Andric return static_cast<bool>(__x); 13040b57cec5SDimitry Andric} 13050b57cec5SDimitry Andric 13060b57cec5SDimitry Andrictemplate <class _Tp> 13070b57cec5SDimitry Andric_LIBCPP_INLINE_VISIBILITY constexpr 13080b57cec5SDimitry Andricbool 13090b57cec5SDimitry Andricoperator!=(nullopt_t, const optional<_Tp>& __x) noexcept 13100b57cec5SDimitry Andric{ 13110b57cec5SDimitry Andric return static_cast<bool>(__x); 13120b57cec5SDimitry Andric} 13130b57cec5SDimitry Andric 13140b57cec5SDimitry Andrictemplate <class _Tp> 13150b57cec5SDimitry Andric_LIBCPP_INLINE_VISIBILITY constexpr 13160b57cec5SDimitry Andricbool 13170b57cec5SDimitry Andricoperator<(const optional<_Tp>&, nullopt_t) noexcept 13180b57cec5SDimitry Andric{ 13190b57cec5SDimitry Andric return false; 13200b57cec5SDimitry Andric} 13210b57cec5SDimitry Andric 13220b57cec5SDimitry Andrictemplate <class _Tp> 13230b57cec5SDimitry Andric_LIBCPP_INLINE_VISIBILITY constexpr 13240b57cec5SDimitry Andricbool 13250b57cec5SDimitry Andricoperator<(nullopt_t, const optional<_Tp>& __x) noexcept 13260b57cec5SDimitry Andric{ 13270b57cec5SDimitry Andric return static_cast<bool>(__x); 13280b57cec5SDimitry Andric} 13290b57cec5SDimitry Andric 13300b57cec5SDimitry Andrictemplate <class _Tp> 13310b57cec5SDimitry Andric_LIBCPP_INLINE_VISIBILITY constexpr 13320b57cec5SDimitry Andricbool 13330b57cec5SDimitry Andricoperator<=(const optional<_Tp>& __x, nullopt_t) noexcept 13340b57cec5SDimitry Andric{ 13350b57cec5SDimitry Andric return !static_cast<bool>(__x); 13360b57cec5SDimitry Andric} 13370b57cec5SDimitry Andric 13380b57cec5SDimitry Andrictemplate <class _Tp> 13390b57cec5SDimitry Andric_LIBCPP_INLINE_VISIBILITY constexpr 13400b57cec5SDimitry Andricbool 13410b57cec5SDimitry Andricoperator<=(nullopt_t, const optional<_Tp>&) noexcept 13420b57cec5SDimitry Andric{ 13430b57cec5SDimitry Andric return true; 13440b57cec5SDimitry Andric} 13450b57cec5SDimitry Andric 13460b57cec5SDimitry Andrictemplate <class _Tp> 13470b57cec5SDimitry Andric_LIBCPP_INLINE_VISIBILITY constexpr 13480b57cec5SDimitry Andricbool 13490b57cec5SDimitry Andricoperator>(const optional<_Tp>& __x, nullopt_t) noexcept 13500b57cec5SDimitry Andric{ 13510b57cec5SDimitry Andric return static_cast<bool>(__x); 13520b57cec5SDimitry Andric} 13530b57cec5SDimitry Andric 13540b57cec5SDimitry Andrictemplate <class _Tp> 13550b57cec5SDimitry Andric_LIBCPP_INLINE_VISIBILITY constexpr 13560b57cec5SDimitry Andricbool 13570b57cec5SDimitry Andricoperator>(nullopt_t, const optional<_Tp>&) noexcept 13580b57cec5SDimitry Andric{ 13590b57cec5SDimitry Andric return false; 13600b57cec5SDimitry Andric} 13610b57cec5SDimitry Andric 13620b57cec5SDimitry Andrictemplate <class _Tp> 13630b57cec5SDimitry Andric_LIBCPP_INLINE_VISIBILITY constexpr 13640b57cec5SDimitry Andricbool 13650b57cec5SDimitry Andricoperator>=(const optional<_Tp>&, nullopt_t) noexcept 13660b57cec5SDimitry Andric{ 13670b57cec5SDimitry Andric return true; 13680b57cec5SDimitry Andric} 13690b57cec5SDimitry Andric 13700b57cec5SDimitry Andrictemplate <class _Tp> 13710b57cec5SDimitry Andric_LIBCPP_INLINE_VISIBILITY constexpr 13720b57cec5SDimitry Andricbool 13730b57cec5SDimitry Andricoperator>=(nullopt_t, const optional<_Tp>& __x) noexcept 13740b57cec5SDimitry Andric{ 13750b57cec5SDimitry Andric return !static_cast<bool>(__x); 13760b57cec5SDimitry Andric} 13770b57cec5SDimitry Andric 13780b57cec5SDimitry Andric// Comparisons with T 13790b57cec5SDimitry Andrictemplate <class _Tp, class _Up> 13800b57cec5SDimitry Andric_LIBCPP_INLINE_VISIBILITY constexpr 1381349cc55cSDimitry Andricenable_if_t< 1382*bdd1243dSDimitry Andric is_convertible_v<decltype(std::declval<const _Tp&>() == 1383*bdd1243dSDimitry Andric std::declval<const _Up&>()), bool>, 13840b57cec5SDimitry Andric bool 13850b57cec5SDimitry Andric> 13860b57cec5SDimitry Andricoperator==(const optional<_Tp>& __x, const _Up& __v) 13870b57cec5SDimitry Andric{ 13880b57cec5SDimitry Andric return static_cast<bool>(__x) ? *__x == __v : false; 13890b57cec5SDimitry Andric} 13900b57cec5SDimitry Andric 13910b57cec5SDimitry Andrictemplate <class _Tp, class _Up> 13920b57cec5SDimitry Andric_LIBCPP_INLINE_VISIBILITY constexpr 1393349cc55cSDimitry Andricenable_if_t< 1394*bdd1243dSDimitry Andric is_convertible_v<decltype(std::declval<const _Tp&>() == 1395*bdd1243dSDimitry Andric std::declval<const _Up&>()), bool>, 13960b57cec5SDimitry Andric bool 13970b57cec5SDimitry Andric> 13980b57cec5SDimitry Andricoperator==(const _Tp& __v, const optional<_Up>& __x) 13990b57cec5SDimitry Andric{ 14000b57cec5SDimitry Andric return static_cast<bool>(__x) ? __v == *__x : false; 14010b57cec5SDimitry Andric} 14020b57cec5SDimitry Andric 14030b57cec5SDimitry Andrictemplate <class _Tp, class _Up> 14040b57cec5SDimitry Andric_LIBCPP_INLINE_VISIBILITY constexpr 1405349cc55cSDimitry Andricenable_if_t< 1406*bdd1243dSDimitry Andric is_convertible_v<decltype(std::declval<const _Tp&>() != 1407*bdd1243dSDimitry Andric std::declval<const _Up&>()), bool>, 14080b57cec5SDimitry Andric bool 14090b57cec5SDimitry Andric> 14100b57cec5SDimitry Andricoperator!=(const optional<_Tp>& __x, const _Up& __v) 14110b57cec5SDimitry Andric{ 14120b57cec5SDimitry Andric return static_cast<bool>(__x) ? *__x != __v : true; 14130b57cec5SDimitry Andric} 14140b57cec5SDimitry Andric 14150b57cec5SDimitry Andrictemplate <class _Tp, class _Up> 14160b57cec5SDimitry Andric_LIBCPP_INLINE_VISIBILITY constexpr 1417349cc55cSDimitry Andricenable_if_t< 1418*bdd1243dSDimitry Andric is_convertible_v<decltype(std::declval<const _Tp&>() != 1419*bdd1243dSDimitry Andric std::declval<const _Up&>()), bool>, 14200b57cec5SDimitry Andric bool 14210b57cec5SDimitry Andric> 14220b57cec5SDimitry Andricoperator!=(const _Tp& __v, const optional<_Up>& __x) 14230b57cec5SDimitry Andric{ 14240b57cec5SDimitry Andric return static_cast<bool>(__x) ? __v != *__x : true; 14250b57cec5SDimitry Andric} 14260b57cec5SDimitry Andric 14270b57cec5SDimitry Andrictemplate <class _Tp, class _Up> 14280b57cec5SDimitry Andric_LIBCPP_INLINE_VISIBILITY constexpr 1429349cc55cSDimitry Andricenable_if_t< 1430*bdd1243dSDimitry Andric is_convertible_v<decltype(std::declval<const _Tp&>() < 1431*bdd1243dSDimitry Andric std::declval<const _Up&>()), bool>, 14320b57cec5SDimitry Andric bool 14330b57cec5SDimitry Andric> 14340b57cec5SDimitry Andricoperator<(const optional<_Tp>& __x, const _Up& __v) 14350b57cec5SDimitry Andric{ 14360b57cec5SDimitry Andric return static_cast<bool>(__x) ? *__x < __v : true; 14370b57cec5SDimitry Andric} 14380b57cec5SDimitry Andric 14390b57cec5SDimitry Andrictemplate <class _Tp, class _Up> 14400b57cec5SDimitry Andric_LIBCPP_INLINE_VISIBILITY constexpr 1441349cc55cSDimitry Andricenable_if_t< 1442*bdd1243dSDimitry Andric is_convertible_v<decltype(std::declval<const _Tp&>() < 1443*bdd1243dSDimitry Andric std::declval<const _Up&>()), bool>, 14440b57cec5SDimitry Andric bool 14450b57cec5SDimitry Andric> 14460b57cec5SDimitry Andricoperator<(const _Tp& __v, const optional<_Up>& __x) 14470b57cec5SDimitry Andric{ 14480b57cec5SDimitry Andric return static_cast<bool>(__x) ? __v < *__x : false; 14490b57cec5SDimitry Andric} 14500b57cec5SDimitry Andric 14510b57cec5SDimitry Andrictemplate <class _Tp, class _Up> 14520b57cec5SDimitry Andric_LIBCPP_INLINE_VISIBILITY constexpr 1453349cc55cSDimitry Andricenable_if_t< 1454*bdd1243dSDimitry Andric is_convertible_v<decltype(std::declval<const _Tp&>() <= 1455*bdd1243dSDimitry Andric std::declval<const _Up&>()), bool>, 14560b57cec5SDimitry Andric bool 14570b57cec5SDimitry Andric> 14580b57cec5SDimitry Andricoperator<=(const optional<_Tp>& __x, const _Up& __v) 14590b57cec5SDimitry Andric{ 14600b57cec5SDimitry Andric return static_cast<bool>(__x) ? *__x <= __v : true; 14610b57cec5SDimitry Andric} 14620b57cec5SDimitry Andric 14630b57cec5SDimitry Andrictemplate <class _Tp, class _Up> 14640b57cec5SDimitry Andric_LIBCPP_INLINE_VISIBILITY constexpr 1465349cc55cSDimitry Andricenable_if_t< 1466*bdd1243dSDimitry Andric is_convertible_v<decltype(std::declval<const _Tp&>() <= 1467*bdd1243dSDimitry Andric std::declval<const _Up&>()), bool>, 14680b57cec5SDimitry Andric bool 14690b57cec5SDimitry Andric> 14700b57cec5SDimitry Andricoperator<=(const _Tp& __v, const optional<_Up>& __x) 14710b57cec5SDimitry Andric{ 14720b57cec5SDimitry Andric return static_cast<bool>(__x) ? __v <= *__x : false; 14730b57cec5SDimitry Andric} 14740b57cec5SDimitry Andric 14750b57cec5SDimitry Andrictemplate <class _Tp, class _Up> 14760b57cec5SDimitry Andric_LIBCPP_INLINE_VISIBILITY constexpr 1477349cc55cSDimitry Andricenable_if_t< 1478*bdd1243dSDimitry Andric is_convertible_v<decltype(std::declval<const _Tp&>() > 1479*bdd1243dSDimitry Andric std::declval<const _Up&>()), bool>, 14800b57cec5SDimitry Andric bool 14810b57cec5SDimitry Andric> 14820b57cec5SDimitry Andricoperator>(const optional<_Tp>& __x, const _Up& __v) 14830b57cec5SDimitry Andric{ 14840b57cec5SDimitry Andric return static_cast<bool>(__x) ? *__x > __v : false; 14850b57cec5SDimitry Andric} 14860b57cec5SDimitry Andric 14870b57cec5SDimitry Andrictemplate <class _Tp, class _Up> 14880b57cec5SDimitry Andric_LIBCPP_INLINE_VISIBILITY constexpr 1489349cc55cSDimitry Andricenable_if_t< 1490*bdd1243dSDimitry Andric is_convertible_v<decltype(std::declval<const _Tp&>() > 1491*bdd1243dSDimitry Andric std::declval<const _Up&>()), bool>, 14920b57cec5SDimitry Andric bool 14930b57cec5SDimitry Andric> 14940b57cec5SDimitry Andricoperator>(const _Tp& __v, const optional<_Up>& __x) 14950b57cec5SDimitry Andric{ 14960b57cec5SDimitry Andric return static_cast<bool>(__x) ? __v > *__x : true; 14970b57cec5SDimitry Andric} 14980b57cec5SDimitry Andric 14990b57cec5SDimitry Andrictemplate <class _Tp, class _Up> 15000b57cec5SDimitry Andric_LIBCPP_INLINE_VISIBILITY constexpr 1501349cc55cSDimitry Andricenable_if_t< 1502*bdd1243dSDimitry Andric is_convertible_v<decltype(std::declval<const _Tp&>() >= 1503*bdd1243dSDimitry Andric std::declval<const _Up&>()), bool>, 15040b57cec5SDimitry Andric bool 15050b57cec5SDimitry Andric> 15060b57cec5SDimitry Andricoperator>=(const optional<_Tp>& __x, const _Up& __v) 15070b57cec5SDimitry Andric{ 15080b57cec5SDimitry Andric return static_cast<bool>(__x) ? *__x >= __v : false; 15090b57cec5SDimitry Andric} 15100b57cec5SDimitry Andric 15110b57cec5SDimitry Andrictemplate <class _Tp, class _Up> 15120b57cec5SDimitry Andric_LIBCPP_INLINE_VISIBILITY constexpr 1513349cc55cSDimitry Andricenable_if_t< 1514*bdd1243dSDimitry Andric is_convertible_v<decltype(std::declval<const _Tp&>() >= 1515*bdd1243dSDimitry Andric std::declval<const _Up&>()), bool>, 15160b57cec5SDimitry Andric bool 15170b57cec5SDimitry Andric> 15180b57cec5SDimitry Andricoperator>=(const _Tp& __v, const optional<_Up>& __x) 15190b57cec5SDimitry Andric{ 15200b57cec5SDimitry Andric return static_cast<bool>(__x) ? __v >= *__x : true; 15210b57cec5SDimitry Andric} 15220b57cec5SDimitry Andric 15230b57cec5SDimitry Andric 15240b57cec5SDimitry Andrictemplate <class _Tp> 1525*bdd1243dSDimitry Andricinline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 1526349cc55cSDimitry Andricenable_if_t< 15270b57cec5SDimitry Andric is_move_constructible_v<_Tp> && is_swappable_v<_Tp>, 15280b57cec5SDimitry Andric void 15290b57cec5SDimitry Andric> 15300b57cec5SDimitry Andricswap(optional<_Tp>& __x, optional<_Tp>& __y) noexcept(noexcept(__x.swap(__y))) 15310b57cec5SDimitry Andric{ 15320b57cec5SDimitry Andric __x.swap(__y); 15330b57cec5SDimitry Andric} 15340b57cec5SDimitry Andric 15350b57cec5SDimitry Andrictemplate <class _Tp> 15360b57cec5SDimitry Andric_LIBCPP_INLINE_VISIBILITY constexpr 15370b57cec5SDimitry Andricoptional<decay_t<_Tp>> make_optional(_Tp&& __v) 15380b57cec5SDimitry Andric{ 15390b57cec5SDimitry Andric return optional<decay_t<_Tp>>(_VSTD::forward<_Tp>(__v)); 15400b57cec5SDimitry Andric} 15410b57cec5SDimitry Andric 15420b57cec5SDimitry Andrictemplate <class _Tp, class... _Args> 15430b57cec5SDimitry Andric_LIBCPP_INLINE_VISIBILITY constexpr 15440b57cec5SDimitry Andricoptional<_Tp> make_optional(_Args&&... __args) 15450b57cec5SDimitry Andric{ 15460b57cec5SDimitry Andric return optional<_Tp>(in_place, _VSTD::forward<_Args>(__args)...); 15470b57cec5SDimitry Andric} 15480b57cec5SDimitry Andric 15490b57cec5SDimitry Andrictemplate <class _Tp, class _Up, class... _Args> 15500b57cec5SDimitry Andric_LIBCPP_INLINE_VISIBILITY constexpr 15510b57cec5SDimitry Andricoptional<_Tp> make_optional(initializer_list<_Up> __il, _Args&&... __args) 15520b57cec5SDimitry Andric{ 15530b57cec5SDimitry Andric return optional<_Tp>(in_place, __il, _VSTD::forward<_Args>(__args)...); 15540b57cec5SDimitry Andric} 15550b57cec5SDimitry Andric 15560b57cec5SDimitry Andrictemplate <class _Tp> 15570b57cec5SDimitry Andricstruct _LIBCPP_TEMPLATE_VIS hash< 15580b57cec5SDimitry Andric __enable_hash_helper<optional<_Tp>, remove_const_t<_Tp>> 15590b57cec5SDimitry Andric> 15600b57cec5SDimitry Andric{ 1561fe6060f1SDimitry Andric#if _LIBCPP_STD_VER <= 17 || defined(_LIBCPP_ENABLE_CXX20_REMOVED_BINDER_TYPEDEFS) 1562fe6060f1SDimitry Andric _LIBCPP_DEPRECATED_IN_CXX17 typedef optional<_Tp> argument_type; 1563fe6060f1SDimitry Andric _LIBCPP_DEPRECATED_IN_CXX17 typedef size_t result_type; 1564fe6060f1SDimitry Andric#endif 15650b57cec5SDimitry Andric 15660b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY 1567fe6060f1SDimitry Andric size_t operator()(const optional<_Tp>& __opt) const 15680b57cec5SDimitry Andric { 15690b57cec5SDimitry Andric return static_cast<bool>(__opt) ? hash<remove_const_t<_Tp>>()(*__opt) : 0; 15700b57cec5SDimitry Andric } 15710b57cec5SDimitry Andric}; 15720b57cec5SDimitry Andric 15730b57cec5SDimitry Andric_LIBCPP_END_NAMESPACE_STD 15740b57cec5SDimitry Andric 15750b57cec5SDimitry Andric#endif // _LIBCPP_STD_VER > 14 15760b57cec5SDimitry Andric 1577*bdd1243dSDimitry Andric#if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER <= 20 1578*bdd1243dSDimitry Andric# include <atomic> 1579*bdd1243dSDimitry Andric# include <climits> 1580*bdd1243dSDimitry Andric# include <concepts> 1581*bdd1243dSDimitry Andric# include <ctime> 1582*bdd1243dSDimitry Andric# include <iterator> 1583*bdd1243dSDimitry Andric# include <memory> 1584*bdd1243dSDimitry Andric# include <ratio> 1585*bdd1243dSDimitry Andric# include <tuple> 1586*bdd1243dSDimitry Andric# include <typeinfo> 1587*bdd1243dSDimitry Andric# include <utility> 1588*bdd1243dSDimitry Andric# include <variant> 1589*bdd1243dSDimitry Andric#endif 1590*bdd1243dSDimitry Andric 15910b57cec5SDimitry Andric#endif // _LIBCPP_OPTIONAL 1592