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> 186*5f757f3fSDimitry 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 24806c3fb27SDimitry Andricclass _LIBCPP_EXPORTED_FROM_ABI _LIBCPP_AVAILABILITY_BAD_OPTIONAL_ACCESS bad_optional_access 2490b57cec5SDimitry Andric : public exception 2500b57cec5SDimitry Andric{ 2510b57cec5SDimitry Andricpublic: 252*5f757f3fSDimitry Andric _LIBCPP_HIDE_FROM_ABI bad_optional_access() _NOEXCEPT = default; 253*5f757f3fSDimitry Andric _LIBCPP_HIDE_FROM_ABI bad_optional_access(const bad_optional_access&) _NOEXCEPT = default; 254*5f757f3fSDimitry Andric _LIBCPP_HIDE_FROM_ABI bad_optional_access& operator=(const bad_optional_access&) _NOEXCEPT = default; 2550b57cec5SDimitry Andric // Get the key function ~bad_optional_access() into the dylib 256bdd1243dSDimitry Andric ~bad_optional_access() _NOEXCEPT override; 257bdd1243dSDimitry Andric const char* what() const _NOEXCEPT override; 2580b57cec5SDimitry Andric}; 2590b57cec5SDimitry Andric 2600eae32dcSDimitry Andric} // namespace std 2610b57cec5SDimitry Andric 26206c3fb27SDimitry Andric#if _LIBCPP_STD_VER >= 17 2630b57cec5SDimitry Andric 2640b57cec5SDimitry Andric_LIBCPP_BEGIN_NAMESPACE_STD 2650b57cec5SDimitry Andric 2660b57cec5SDimitry Andric_LIBCPP_NORETURN 267*5f757f3fSDimitry Andricinline _LIBCPP_HIDE_FROM_ABI 2680b57cec5SDimitry Andric_LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS 2690b57cec5SDimitry Andricvoid __throw_bad_optional_access() { 27006c3fb27SDimitry Andric#ifndef _LIBCPP_HAS_NO_EXCEPTIONS 2710b57cec5SDimitry Andric throw bad_optional_access(); 2720b57cec5SDimitry Andric#else 27306c3fb27SDimitry Andric _LIBCPP_VERBOSE_ABORT("bad_optional_access was thrown in -fno-exceptions mode"); 2740b57cec5SDimitry Andric#endif 2750b57cec5SDimitry Andric} 2760b57cec5SDimitry Andric 2770b57cec5SDimitry Andricstruct nullopt_t 2780b57cec5SDimitry Andric{ 27906c3fb27SDimitry Andric struct __secret_tag { explicit __secret_tag() = default; }; 280*5f757f3fSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr explicit nullopt_t(__secret_tag, __secret_tag) noexcept {} 2810b57cec5SDimitry Andric}; 2820b57cec5SDimitry Andric 283349cc55cSDimitry Andricinline constexpr nullopt_t nullopt{nullopt_t::__secret_tag{}, nullopt_t::__secret_tag{}}; 2840b57cec5SDimitry Andric 2850eae32dcSDimitry Andricstruct __optional_construct_from_invoke_tag {}; 2860eae32dcSDimitry Andric 2870b57cec5SDimitry Andrictemplate <class _Tp, bool = is_trivially_destructible<_Tp>::value> 2880b57cec5SDimitry Andricstruct __optional_destruct_base; 2890b57cec5SDimitry Andric 2900b57cec5SDimitry Andrictemplate <class _Tp> 2910b57cec5SDimitry Andricstruct __optional_destruct_base<_Tp, false> 2920b57cec5SDimitry Andric{ 2930b57cec5SDimitry Andric typedef _Tp value_type; 2940b57cec5SDimitry Andric static_assert(is_object_v<value_type>, 2950b57cec5SDimitry Andric "instantiation of optional with a non-object type is undefined behavior"); 2960b57cec5SDimitry Andric union 2970b57cec5SDimitry Andric { 2980b57cec5SDimitry Andric char __null_state_; 2990b57cec5SDimitry Andric value_type __val_; 3000b57cec5SDimitry Andric }; 3010b57cec5SDimitry Andric bool __engaged_; 3020b57cec5SDimitry Andric 303*5f757f3fSDimitry Andric _LIBCPP_HIDE_FROM_ABI 304bdd1243dSDimitry Andric _LIBCPP_CONSTEXPR_SINCE_CXX20 ~__optional_destruct_base() 3050b57cec5SDimitry Andric { 3060b57cec5SDimitry Andric if (__engaged_) 3070b57cec5SDimitry Andric __val_.~value_type(); 3080b57cec5SDimitry Andric } 3090b57cec5SDimitry Andric 310*5f757f3fSDimitry Andric _LIBCPP_HIDE_FROM_ABI 3110b57cec5SDimitry Andric constexpr __optional_destruct_base() noexcept 3120b57cec5SDimitry Andric : __null_state_(), 3130b57cec5SDimitry Andric __engaged_(false) {} 3140b57cec5SDimitry Andric 3150b57cec5SDimitry Andric template <class... _Args> 316*5f757f3fSDimitry Andric _LIBCPP_HIDE_FROM_ABI 3170b57cec5SDimitry Andric constexpr explicit __optional_destruct_base(in_place_t, _Args&&... __args) 318*5f757f3fSDimitry Andric : __val_(std::forward<_Args>(__args)...), 3190b57cec5SDimitry Andric __engaged_(true) {} 3200b57cec5SDimitry Andric 32106c3fb27SDimitry Andric#if _LIBCPP_STD_VER >= 23 3220eae32dcSDimitry Andric template <class _Fp, class... _Args> 3230eae32dcSDimitry Andric _LIBCPP_HIDE_FROM_ABI 3240eae32dcSDimitry Andric constexpr __optional_destruct_base(__optional_construct_from_invoke_tag, _Fp&& __f, _Args&&... __args) 325*5f757f3fSDimitry Andric : __val_(std::invoke(std::forward<_Fp>(__f), std::forward<_Args>(__args)...)), __engaged_(true) {} 3260eae32dcSDimitry Andric#endif 3270eae32dcSDimitry Andric 328*5f757f3fSDimitry Andric _LIBCPP_HIDE_FROM_ABI 329bdd1243dSDimitry Andric _LIBCPP_CONSTEXPR_SINCE_CXX20 void reset() noexcept 3300b57cec5SDimitry Andric { 3310b57cec5SDimitry Andric if (__engaged_) 3320b57cec5SDimitry Andric { 3330b57cec5SDimitry Andric __val_.~value_type(); 3340b57cec5SDimitry Andric __engaged_ = false; 3350b57cec5SDimitry Andric } 3360b57cec5SDimitry Andric } 3370b57cec5SDimitry Andric}; 3380b57cec5SDimitry Andric 3390b57cec5SDimitry Andrictemplate <class _Tp> 3400b57cec5SDimitry Andricstruct __optional_destruct_base<_Tp, true> 3410b57cec5SDimitry Andric{ 3420b57cec5SDimitry Andric typedef _Tp value_type; 3430b57cec5SDimitry Andric static_assert(is_object_v<value_type>, 3440b57cec5SDimitry Andric "instantiation of optional with a non-object type is undefined behavior"); 3450b57cec5SDimitry Andric union 3460b57cec5SDimitry Andric { 3470b57cec5SDimitry Andric char __null_state_; 3480b57cec5SDimitry Andric value_type __val_; 3490b57cec5SDimitry Andric }; 3500b57cec5SDimitry Andric bool __engaged_; 3510b57cec5SDimitry Andric 352*5f757f3fSDimitry Andric _LIBCPP_HIDE_FROM_ABI 3530b57cec5SDimitry Andric constexpr __optional_destruct_base() noexcept 3540b57cec5SDimitry Andric : __null_state_(), 3550b57cec5SDimitry Andric __engaged_(false) {} 3560b57cec5SDimitry Andric 3570b57cec5SDimitry Andric template <class... _Args> 358*5f757f3fSDimitry Andric _LIBCPP_HIDE_FROM_ABI 3590b57cec5SDimitry Andric constexpr explicit __optional_destruct_base(in_place_t, _Args&&... __args) 360*5f757f3fSDimitry Andric : __val_(std::forward<_Args>(__args)...), 3610b57cec5SDimitry Andric __engaged_(true) {} 3620b57cec5SDimitry Andric 36306c3fb27SDimitry Andric#if _LIBCPP_STD_VER >= 23 3640eae32dcSDimitry Andric template <class _Fp, class... _Args> 3650eae32dcSDimitry Andric _LIBCPP_HIDE_FROM_ABI 3660eae32dcSDimitry Andric constexpr __optional_destruct_base(__optional_construct_from_invoke_tag, _Fp&& __f, _Args&&... __args) 367*5f757f3fSDimitry Andric : __val_(std::invoke(std::forward<_Fp>(__f), std::forward<_Args>(__args)...)), __engaged_(true) {} 3680eae32dcSDimitry Andric#endif 3690eae32dcSDimitry Andric 370*5f757f3fSDimitry Andric _LIBCPP_HIDE_FROM_ABI 371bdd1243dSDimitry Andric _LIBCPP_CONSTEXPR_SINCE_CXX20 void reset() noexcept 3720b57cec5SDimitry Andric { 3730b57cec5SDimitry Andric if (__engaged_) 3740b57cec5SDimitry Andric { 3750b57cec5SDimitry Andric __engaged_ = false; 3760b57cec5SDimitry Andric } 3770b57cec5SDimitry Andric } 3780b57cec5SDimitry Andric}; 3790b57cec5SDimitry Andric 3800b57cec5SDimitry Andrictemplate <class _Tp, bool = is_reference<_Tp>::value> 3810b57cec5SDimitry Andricstruct __optional_storage_base : __optional_destruct_base<_Tp> 3820b57cec5SDimitry Andric{ 3830b57cec5SDimitry Andric using __base = __optional_destruct_base<_Tp>; 3840b57cec5SDimitry Andric using value_type = _Tp; 3850b57cec5SDimitry Andric using __base::__base; 3860b57cec5SDimitry Andric 387*5f757f3fSDimitry Andric _LIBCPP_HIDE_FROM_ABI 3880b57cec5SDimitry Andric constexpr bool has_value() const noexcept 3890b57cec5SDimitry Andric { 3900b57cec5SDimitry Andric return this->__engaged_; 3910b57cec5SDimitry Andric } 3920b57cec5SDimitry Andric 393*5f757f3fSDimitry Andric _LIBCPP_HIDE_FROM_ABI 3940b57cec5SDimitry Andric constexpr value_type& __get() & noexcept 3950b57cec5SDimitry Andric { 3960b57cec5SDimitry Andric return this->__val_; 3970b57cec5SDimitry Andric } 398*5f757f3fSDimitry Andric _LIBCPP_HIDE_FROM_ABI 3990b57cec5SDimitry Andric constexpr const value_type& __get() const& noexcept 4000b57cec5SDimitry Andric { 4010b57cec5SDimitry Andric return this->__val_; 4020b57cec5SDimitry Andric } 403*5f757f3fSDimitry Andric _LIBCPP_HIDE_FROM_ABI 4040b57cec5SDimitry Andric constexpr value_type&& __get() && noexcept 4050b57cec5SDimitry Andric { 406*5f757f3fSDimitry Andric return std::move(this->__val_); 4070b57cec5SDimitry Andric } 408*5f757f3fSDimitry Andric _LIBCPP_HIDE_FROM_ABI 4090b57cec5SDimitry Andric constexpr const value_type&& __get() const&& noexcept 4100b57cec5SDimitry Andric { 411*5f757f3fSDimitry Andric return std::move(this->__val_); 4120b57cec5SDimitry Andric } 4130b57cec5SDimitry Andric 4140b57cec5SDimitry Andric template <class... _Args> 415*5f757f3fSDimitry Andric _LIBCPP_HIDE_FROM_ABI 416bdd1243dSDimitry Andric _LIBCPP_CONSTEXPR_SINCE_CXX20 void __construct(_Args&&... __args) 4170b57cec5SDimitry Andric { 41806c3fb27SDimitry Andric _LIBCPP_ASSERT_INTERNAL(!has_value(), "__construct called for engaged __optional_storage"); 419*5f757f3fSDimitry Andric std::__construct_at(std::addressof(this->__val_), std::forward<_Args>(__args)...); 4200b57cec5SDimitry Andric this->__engaged_ = true; 4210b57cec5SDimitry Andric } 4220b57cec5SDimitry Andric 4230b57cec5SDimitry Andric template <class _That> 424*5f757f3fSDimitry Andric _LIBCPP_HIDE_FROM_ABI 425bdd1243dSDimitry Andric _LIBCPP_CONSTEXPR_SINCE_CXX20 void __construct_from(_That&& __opt) 4260b57cec5SDimitry Andric { 4270b57cec5SDimitry Andric if (__opt.has_value()) 428*5f757f3fSDimitry Andric __construct(std::forward<_That>(__opt).__get()); 4290b57cec5SDimitry Andric } 4300b57cec5SDimitry Andric 4310b57cec5SDimitry Andric template <class _That> 432*5f757f3fSDimitry Andric _LIBCPP_HIDE_FROM_ABI 433bdd1243dSDimitry Andric _LIBCPP_CONSTEXPR_SINCE_CXX20 void __assign_from(_That&& __opt) 4340b57cec5SDimitry Andric { 4350b57cec5SDimitry Andric if (this->__engaged_ == __opt.has_value()) 4360b57cec5SDimitry Andric { 4370b57cec5SDimitry Andric if (this->__engaged_) 438*5f757f3fSDimitry Andric this->__val_ = std::forward<_That>(__opt).__get(); 4390b57cec5SDimitry Andric } 4400b57cec5SDimitry Andric else 4410b57cec5SDimitry Andric { 4420b57cec5SDimitry Andric if (this->__engaged_) 4430b57cec5SDimitry Andric this->reset(); 4440b57cec5SDimitry Andric else 445*5f757f3fSDimitry Andric __construct(std::forward<_That>(__opt).__get()); 4460b57cec5SDimitry Andric } 4470b57cec5SDimitry Andric } 4480b57cec5SDimitry Andric}; 4490b57cec5SDimitry Andric 45081ad6265SDimitry Andric// optional<T&> is currently required to be ill-formed. However, it may 45181ad6265SDimitry Andric// be allowed in the future. For this reason, it has already been implemented 45281ad6265SDimitry Andric// to ensure we can make the change in an ABI-compatible manner. 4530b57cec5SDimitry Andrictemplate <class _Tp> 4540b57cec5SDimitry Andricstruct __optional_storage_base<_Tp, true> 4550b57cec5SDimitry Andric{ 4560b57cec5SDimitry Andric using value_type = _Tp; 4570b57cec5SDimitry Andric using __raw_type = remove_reference_t<_Tp>; 4580b57cec5SDimitry Andric __raw_type* __value_; 4590b57cec5SDimitry Andric 4600b57cec5SDimitry Andric template <class _Up> 46106c3fb27SDimitry Andric static _LIBCPP_HIDE_FROM_ABI constexpr bool __can_bind_reference() { 462bdd1243dSDimitry Andric using _RawUp = __libcpp_remove_reference_t<_Up>; 4630b57cec5SDimitry Andric using _UpPtr = _RawUp*; 464bdd1243dSDimitry Andric using _RawTp = __libcpp_remove_reference_t<_Tp>; 4650b57cec5SDimitry Andric using _TpPtr = _RawTp*; 4660b57cec5SDimitry Andric using _CheckLValueArg = integral_constant<bool, 4670b57cec5SDimitry Andric (is_lvalue_reference<_Up>::value && is_convertible<_UpPtr, _TpPtr>::value) 4680b57cec5SDimitry Andric || is_same<_RawUp, reference_wrapper<_RawTp>>::value 469bdd1243dSDimitry Andric || is_same<_RawUp, reference_wrapper<__remove_const_t<_RawTp>>>::value 4700b57cec5SDimitry Andric >; 4710b57cec5SDimitry Andric return (is_lvalue_reference<_Tp>::value && _CheckLValueArg::value) 4720b57cec5SDimitry Andric || (is_rvalue_reference<_Tp>::value && !is_lvalue_reference<_Up>::value && 4730b57cec5SDimitry Andric is_convertible<_UpPtr, _TpPtr>::value); 4740b57cec5SDimitry Andric } 4750b57cec5SDimitry Andric 476*5f757f3fSDimitry Andric _LIBCPP_HIDE_FROM_ABI 4770b57cec5SDimitry Andric constexpr __optional_storage_base() noexcept 4780b57cec5SDimitry Andric : __value_(nullptr) {} 4790b57cec5SDimitry Andric 4800b57cec5SDimitry Andric template <class _UArg> 481*5f757f3fSDimitry Andric _LIBCPP_HIDE_FROM_ABI 4820b57cec5SDimitry Andric constexpr explicit __optional_storage_base(in_place_t, _UArg&& __uarg) 483*5f757f3fSDimitry Andric : __value_(std::addressof(__uarg)) 4840b57cec5SDimitry Andric { 4850b57cec5SDimitry Andric static_assert(__can_bind_reference<_UArg>(), 4860b57cec5SDimitry Andric "Attempted to construct a reference element in tuple from a " 4870b57cec5SDimitry Andric "possible temporary"); 4880b57cec5SDimitry Andric } 4890b57cec5SDimitry Andric 490*5f757f3fSDimitry Andric _LIBCPP_HIDE_FROM_ABI 491bdd1243dSDimitry Andric _LIBCPP_CONSTEXPR_SINCE_CXX20 void reset() noexcept { __value_ = nullptr; } 4920b57cec5SDimitry Andric 493*5f757f3fSDimitry Andric _LIBCPP_HIDE_FROM_ABI 4940b57cec5SDimitry Andric constexpr bool has_value() const noexcept 4950b57cec5SDimitry Andric { return __value_ != nullptr; } 4960b57cec5SDimitry Andric 497*5f757f3fSDimitry Andric _LIBCPP_HIDE_FROM_ABI 4980b57cec5SDimitry Andric constexpr value_type& __get() const& noexcept 4990b57cec5SDimitry Andric { return *__value_; } 5000b57cec5SDimitry Andric 501*5f757f3fSDimitry Andric _LIBCPP_HIDE_FROM_ABI 5020b57cec5SDimitry Andric constexpr value_type&& __get() const&& noexcept 503*5f757f3fSDimitry Andric { return std::forward<value_type>(*__value_); } 5040b57cec5SDimitry Andric 5050b57cec5SDimitry Andric template <class _UArg> 506*5f757f3fSDimitry Andric _LIBCPP_HIDE_FROM_ABI 507bdd1243dSDimitry Andric _LIBCPP_CONSTEXPR_SINCE_CXX20 void __construct(_UArg&& __val) 5080b57cec5SDimitry Andric { 50906c3fb27SDimitry Andric _LIBCPP_ASSERT_INTERNAL(!has_value(), "__construct called for engaged __optional_storage"); 5100b57cec5SDimitry Andric static_assert(__can_bind_reference<_UArg>(), 5110b57cec5SDimitry Andric "Attempted to construct a reference element in tuple from a " 5120b57cec5SDimitry Andric "possible temporary"); 513*5f757f3fSDimitry Andric __value_ = std::addressof(__val); 5140b57cec5SDimitry Andric } 5150b57cec5SDimitry Andric 5160b57cec5SDimitry Andric template <class _That> 517*5f757f3fSDimitry Andric _LIBCPP_HIDE_FROM_ABI 518bdd1243dSDimitry Andric _LIBCPP_CONSTEXPR_SINCE_CXX20 void __construct_from(_That&& __opt) 5190b57cec5SDimitry Andric { 5200b57cec5SDimitry Andric if (__opt.has_value()) 521*5f757f3fSDimitry Andric __construct(std::forward<_That>(__opt).__get()); 5220b57cec5SDimitry Andric } 5230b57cec5SDimitry Andric 5240b57cec5SDimitry Andric template <class _That> 525*5f757f3fSDimitry Andric _LIBCPP_HIDE_FROM_ABI 526bdd1243dSDimitry Andric _LIBCPP_CONSTEXPR_SINCE_CXX20 void __assign_from(_That&& __opt) 5270b57cec5SDimitry Andric { 5280b57cec5SDimitry Andric if (has_value() == __opt.has_value()) 5290b57cec5SDimitry Andric { 5300b57cec5SDimitry Andric if (has_value()) 531*5f757f3fSDimitry Andric *__value_ = std::forward<_That>(__opt).__get(); 5320b57cec5SDimitry Andric } 5330b57cec5SDimitry Andric else 5340b57cec5SDimitry Andric { 5350b57cec5SDimitry Andric if (has_value()) 5360b57cec5SDimitry Andric reset(); 5370b57cec5SDimitry Andric else 538*5f757f3fSDimitry Andric __construct(std::forward<_That>(__opt).__get()); 5390b57cec5SDimitry Andric } 5400b57cec5SDimitry Andric } 5410b57cec5SDimitry Andric}; 5420b57cec5SDimitry Andric 5430b57cec5SDimitry Andrictemplate <class _Tp, bool = is_trivially_copy_constructible<_Tp>::value> 5440b57cec5SDimitry Andricstruct __optional_copy_base : __optional_storage_base<_Tp> 5450b57cec5SDimitry Andric{ 5460b57cec5SDimitry Andric using __optional_storage_base<_Tp>::__optional_storage_base; 5470b57cec5SDimitry Andric}; 5480b57cec5SDimitry Andric 5490b57cec5SDimitry Andrictemplate <class _Tp> 5500b57cec5SDimitry Andricstruct __optional_copy_base<_Tp, false> : __optional_storage_base<_Tp> 5510b57cec5SDimitry Andric{ 5520b57cec5SDimitry Andric using __optional_storage_base<_Tp>::__optional_storage_base; 5530b57cec5SDimitry Andric 554*5f757f3fSDimitry Andric _LIBCPP_HIDE_FROM_ABI 5550b57cec5SDimitry Andric __optional_copy_base() = default; 5560b57cec5SDimitry Andric 557*5f757f3fSDimitry Andric _LIBCPP_HIDE_FROM_ABI 558bdd1243dSDimitry Andric _LIBCPP_CONSTEXPR_SINCE_CXX20 __optional_copy_base(const __optional_copy_base& __opt) 5590b57cec5SDimitry Andric { 5600b57cec5SDimitry Andric this->__construct_from(__opt); 5610b57cec5SDimitry Andric } 5620b57cec5SDimitry Andric 563*5f757f3fSDimitry Andric _LIBCPP_HIDE_FROM_ABI 5640b57cec5SDimitry Andric __optional_copy_base(__optional_copy_base&&) = default; 565*5f757f3fSDimitry Andric _LIBCPP_HIDE_FROM_ABI 5660b57cec5SDimitry Andric __optional_copy_base& operator=(const __optional_copy_base&) = default; 567*5f757f3fSDimitry Andric _LIBCPP_HIDE_FROM_ABI 5680b57cec5SDimitry Andric __optional_copy_base& operator=(__optional_copy_base&&) = default; 5690b57cec5SDimitry Andric}; 5700b57cec5SDimitry Andric 5710b57cec5SDimitry Andrictemplate <class _Tp, bool = is_trivially_move_constructible<_Tp>::value> 5720b57cec5SDimitry Andricstruct __optional_move_base : __optional_copy_base<_Tp> 5730b57cec5SDimitry Andric{ 5740b57cec5SDimitry Andric using __optional_copy_base<_Tp>::__optional_copy_base; 5750b57cec5SDimitry Andric}; 5760b57cec5SDimitry Andric 5770b57cec5SDimitry Andrictemplate <class _Tp> 5780b57cec5SDimitry Andricstruct __optional_move_base<_Tp, false> : __optional_copy_base<_Tp> 5790b57cec5SDimitry Andric{ 5800b57cec5SDimitry Andric using value_type = _Tp; 5810b57cec5SDimitry Andric using __optional_copy_base<_Tp>::__optional_copy_base; 5820b57cec5SDimitry Andric 583*5f757f3fSDimitry Andric _LIBCPP_HIDE_FROM_ABI 5840b57cec5SDimitry Andric __optional_move_base() = default; 585*5f757f3fSDimitry Andric _LIBCPP_HIDE_FROM_ABI 5860b57cec5SDimitry Andric __optional_move_base(const __optional_move_base&) = default; 5870b57cec5SDimitry Andric 588*5f757f3fSDimitry Andric _LIBCPP_HIDE_FROM_ABI 589bdd1243dSDimitry Andric _LIBCPP_CONSTEXPR_SINCE_CXX20 __optional_move_base(__optional_move_base&& __opt) 5900b57cec5SDimitry Andric noexcept(is_nothrow_move_constructible_v<value_type>) 5910b57cec5SDimitry Andric { 592*5f757f3fSDimitry Andric this->__construct_from(std::move(__opt)); 5930b57cec5SDimitry Andric } 5940b57cec5SDimitry Andric 595*5f757f3fSDimitry Andric _LIBCPP_HIDE_FROM_ABI 5960b57cec5SDimitry Andric __optional_move_base& operator=(const __optional_move_base&) = default; 597*5f757f3fSDimitry Andric _LIBCPP_HIDE_FROM_ABI 5980b57cec5SDimitry Andric __optional_move_base& operator=(__optional_move_base&&) = default; 5990b57cec5SDimitry Andric}; 6000b57cec5SDimitry Andric 6010b57cec5SDimitry Andrictemplate <class _Tp, bool = 6020b57cec5SDimitry Andric is_trivially_destructible<_Tp>::value && 6030b57cec5SDimitry Andric is_trivially_copy_constructible<_Tp>::value && 6040b57cec5SDimitry Andric is_trivially_copy_assignable<_Tp>::value> 6050b57cec5SDimitry Andricstruct __optional_copy_assign_base : __optional_move_base<_Tp> 6060b57cec5SDimitry Andric{ 6070b57cec5SDimitry Andric using __optional_move_base<_Tp>::__optional_move_base; 6080b57cec5SDimitry Andric}; 6090b57cec5SDimitry Andric 6100b57cec5SDimitry Andrictemplate <class _Tp> 6110b57cec5SDimitry Andricstruct __optional_copy_assign_base<_Tp, false> : __optional_move_base<_Tp> 6120b57cec5SDimitry Andric{ 6130b57cec5SDimitry Andric using __optional_move_base<_Tp>::__optional_move_base; 6140b57cec5SDimitry Andric 615*5f757f3fSDimitry Andric _LIBCPP_HIDE_FROM_ABI 6160b57cec5SDimitry Andric __optional_copy_assign_base() = default; 617*5f757f3fSDimitry Andric _LIBCPP_HIDE_FROM_ABI 6180b57cec5SDimitry Andric __optional_copy_assign_base(const __optional_copy_assign_base&) = default; 619*5f757f3fSDimitry Andric _LIBCPP_HIDE_FROM_ABI 6200b57cec5SDimitry Andric __optional_copy_assign_base(__optional_copy_assign_base&&) = default; 6210b57cec5SDimitry Andric 622*5f757f3fSDimitry Andric _LIBCPP_HIDE_FROM_ABI 623bdd1243dSDimitry Andric _LIBCPP_CONSTEXPR_SINCE_CXX20 __optional_copy_assign_base& operator=(const __optional_copy_assign_base& __opt) 6240b57cec5SDimitry Andric { 6250b57cec5SDimitry Andric this->__assign_from(__opt); 6260b57cec5SDimitry Andric return *this; 6270b57cec5SDimitry Andric } 6280b57cec5SDimitry Andric 629*5f757f3fSDimitry Andric _LIBCPP_HIDE_FROM_ABI 6300b57cec5SDimitry Andric __optional_copy_assign_base& operator=(__optional_copy_assign_base&&) = default; 6310b57cec5SDimitry Andric}; 6320b57cec5SDimitry Andric 6330b57cec5SDimitry Andrictemplate <class _Tp, bool = 6340b57cec5SDimitry Andric is_trivially_destructible<_Tp>::value && 6350b57cec5SDimitry Andric is_trivially_move_constructible<_Tp>::value && 6360b57cec5SDimitry Andric is_trivially_move_assignable<_Tp>::value> 6370b57cec5SDimitry Andricstruct __optional_move_assign_base : __optional_copy_assign_base<_Tp> 6380b57cec5SDimitry Andric{ 6390b57cec5SDimitry Andric using __optional_copy_assign_base<_Tp>::__optional_copy_assign_base; 6400b57cec5SDimitry Andric}; 6410b57cec5SDimitry Andric 6420b57cec5SDimitry Andrictemplate <class _Tp> 6430b57cec5SDimitry Andricstruct __optional_move_assign_base<_Tp, false> : __optional_copy_assign_base<_Tp> 6440b57cec5SDimitry Andric{ 6450b57cec5SDimitry Andric using value_type = _Tp; 6460b57cec5SDimitry Andric using __optional_copy_assign_base<_Tp>::__optional_copy_assign_base; 6470b57cec5SDimitry Andric 648*5f757f3fSDimitry Andric _LIBCPP_HIDE_FROM_ABI 6490b57cec5SDimitry Andric __optional_move_assign_base() = default; 650*5f757f3fSDimitry Andric _LIBCPP_HIDE_FROM_ABI 6510b57cec5SDimitry Andric __optional_move_assign_base(const __optional_move_assign_base& __opt) = default; 652*5f757f3fSDimitry Andric _LIBCPP_HIDE_FROM_ABI 6530b57cec5SDimitry Andric __optional_move_assign_base(__optional_move_assign_base&&) = default; 654*5f757f3fSDimitry Andric _LIBCPP_HIDE_FROM_ABI 6550b57cec5SDimitry Andric __optional_move_assign_base& operator=(const __optional_move_assign_base&) = default; 6560b57cec5SDimitry Andric 657*5f757f3fSDimitry Andric _LIBCPP_HIDE_FROM_ABI 658bdd1243dSDimitry Andric _LIBCPP_CONSTEXPR_SINCE_CXX20 __optional_move_assign_base& operator=(__optional_move_assign_base&& __opt) 6590b57cec5SDimitry Andric noexcept(is_nothrow_move_assignable_v<value_type> && 6600b57cec5SDimitry Andric is_nothrow_move_constructible_v<value_type>) 6610b57cec5SDimitry Andric { 662*5f757f3fSDimitry Andric this->__assign_from(std::move(__opt)); 6630b57cec5SDimitry Andric return *this; 6640b57cec5SDimitry Andric } 6650b57cec5SDimitry Andric}; 6660b57cec5SDimitry Andric 6670b57cec5SDimitry Andrictemplate <class _Tp> 6680b57cec5SDimitry Andricusing __optional_sfinae_ctor_base_t = __sfinae_ctor_base< 6690b57cec5SDimitry Andric is_copy_constructible<_Tp>::value, 6700b57cec5SDimitry Andric is_move_constructible<_Tp>::value 6710b57cec5SDimitry Andric>; 6720b57cec5SDimitry Andric 6730b57cec5SDimitry Andrictemplate <class _Tp> 6740b57cec5SDimitry Andricusing __optional_sfinae_assign_base_t = __sfinae_assign_base< 6750b57cec5SDimitry Andric (is_copy_constructible<_Tp>::value && is_copy_assignable<_Tp>::value), 6760b57cec5SDimitry Andric (is_move_constructible<_Tp>::value && is_move_assignable<_Tp>::value) 6770b57cec5SDimitry Andric>; 6780b57cec5SDimitry Andric 6790b57cec5SDimitry Andrictemplate<class _Tp> 6800eae32dcSDimitry Andricclass optional; 68106c3fb27SDimitry Andric 68206c3fb27SDimitry Andric#if _LIBCPP_STD_VER >= 20 68306c3fb27SDimitry Andric 68406c3fb27SDimitry Andrictemplate <class _Tp> 68506c3fb27SDimitry Andricconcept __is_derived_from_optional = requires(const _Tp& __t) { []<class _Up>(const optional<_Up>&) {}(__t); }; 68606c3fb27SDimitry Andric 68706c3fb27SDimitry Andric# endif // _LIBCPP_STD_VER >= 20 68806c3fb27SDimitry Andric 6890eae32dcSDimitry Andrictemplate <class _Tp> 6900eae32dcSDimitry Andricstruct __is_std_optional : false_type {}; 6910eae32dcSDimitry Andrictemplate <class _Tp> struct __is_std_optional<optional<_Tp>> : true_type {}; 6920eae32dcSDimitry Andric 6930eae32dcSDimitry Andrictemplate <class _Tp> 69406c3fb27SDimitry Andricclass _LIBCPP_DECLSPEC_EMPTY_BASES optional 6950b57cec5SDimitry Andric : private __optional_move_assign_base<_Tp> 6960b57cec5SDimitry Andric , private __optional_sfinae_ctor_base_t<_Tp> 6970b57cec5SDimitry Andric , private __optional_sfinae_assign_base_t<_Tp> 6980b57cec5SDimitry Andric{ 6990b57cec5SDimitry Andric using __base = __optional_move_assign_base<_Tp>; 7000b57cec5SDimitry Andricpublic: 7010b57cec5SDimitry Andric using value_type = _Tp; 7020b57cec5SDimitry Andric 7030b57cec5SDimitry Andricprivate: 7040b57cec5SDimitry Andric // Disable the reference extension using this static assert. 705bdd1243dSDimitry Andric static_assert(!is_same_v<__remove_cvref_t<value_type>, in_place_t>, 7060b57cec5SDimitry Andric "instantiation of optional with in_place_t is ill-formed"); 707bdd1243dSDimitry Andric static_assert(!is_same_v<__remove_cvref_t<value_type>, nullopt_t>, 7080b57cec5SDimitry Andric "instantiation of optional with nullopt_t is ill-formed"); 7090b57cec5SDimitry Andric static_assert(!is_reference_v<value_type>, 7100b57cec5SDimitry Andric "instantiation of optional with a reference type is ill-formed"); 7110b57cec5SDimitry Andric static_assert(is_destructible_v<value_type>, 7120b57cec5SDimitry Andric "instantiation of optional with a non-destructible type is ill-formed"); 7130b57cec5SDimitry Andric static_assert(!is_array_v<value_type>, 7140b57cec5SDimitry Andric "instantiation of optional with an array type is ill-formed"); 7150b57cec5SDimitry Andric 7160b57cec5SDimitry Andric // LWG2756: conditionally explicit conversion from _Up 7170b57cec5SDimitry Andric struct _CheckOptionalArgsConstructor { 7180b57cec5SDimitry Andric template <class _Up> 71906c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI static constexpr bool __enable_implicit() { 7200b57cec5SDimitry Andric return is_constructible_v<_Tp, _Up&&> && 7210b57cec5SDimitry Andric is_convertible_v<_Up&&, _Tp>; 7220b57cec5SDimitry Andric } 7230b57cec5SDimitry Andric 7240b57cec5SDimitry Andric template <class _Up> 72506c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI static constexpr bool __enable_explicit() { 7260b57cec5SDimitry Andric return is_constructible_v<_Tp, _Up&&> && 7270b57cec5SDimitry Andric !is_convertible_v<_Up&&, _Tp>; 7280b57cec5SDimitry Andric } 7290b57cec5SDimitry Andric }; 7300b57cec5SDimitry Andric template <class _Up> 7310b57cec5SDimitry Andric using _CheckOptionalArgsCtor = _If< 732bdd1243dSDimitry Andric _IsNotSame<__remove_cvref_t<_Up>, in_place_t>::value && 733*5f757f3fSDimitry Andric _IsNotSame<__remove_cvref_t<_Up>, optional>::value && 734*5f757f3fSDimitry Andric (!is_same_v<remove_cv_t<_Tp>, bool> || !__is_std_optional<__remove_cvref_t<_Up>>::value), 7350b57cec5SDimitry Andric _CheckOptionalArgsConstructor, 7360b57cec5SDimitry Andric __check_tuple_constructor_fail 7370b57cec5SDimitry Andric >; 7380b57cec5SDimitry Andric template <class _QualUp> 7390b57cec5SDimitry Andric struct _CheckOptionalLikeConstructor { 7400b57cec5SDimitry Andric template <class _Up, class _Opt = optional<_Up>> 7410b57cec5SDimitry Andric using __check_constructible_from_opt = _Or< 7420b57cec5SDimitry Andric is_constructible<_Tp, _Opt&>, 7430b57cec5SDimitry Andric is_constructible<_Tp, _Opt const&>, 7440b57cec5SDimitry Andric is_constructible<_Tp, _Opt&&>, 7450b57cec5SDimitry Andric is_constructible<_Tp, _Opt const&&>, 7460b57cec5SDimitry Andric is_convertible<_Opt&, _Tp>, 7470b57cec5SDimitry Andric is_convertible<_Opt const&, _Tp>, 7480b57cec5SDimitry Andric is_convertible<_Opt&&, _Tp>, 7490b57cec5SDimitry Andric is_convertible<_Opt const&&, _Tp> 7500b57cec5SDimitry Andric >; 7510b57cec5SDimitry Andric template <class _Up, class _Opt = optional<_Up>> 7520b57cec5SDimitry Andric using __check_assignable_from_opt = _Or< 7530b57cec5SDimitry Andric is_assignable<_Tp&, _Opt&>, 7540b57cec5SDimitry Andric is_assignable<_Tp&, _Opt const&>, 7550b57cec5SDimitry Andric is_assignable<_Tp&, _Opt&&>, 7560b57cec5SDimitry Andric is_assignable<_Tp&, _Opt const&&> 7570b57cec5SDimitry Andric >; 7580b57cec5SDimitry Andric template <class _Up, class _QUp = _QualUp> 75906c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI static constexpr bool __enable_implicit() { 7600b57cec5SDimitry Andric return is_convertible<_QUp, _Tp>::value && 761*5f757f3fSDimitry Andric (is_same_v<remove_cv_t<_Tp>, bool> || !__check_constructible_from_opt<_Up>::value); 7620b57cec5SDimitry Andric } 7630b57cec5SDimitry Andric template <class _Up, class _QUp = _QualUp> 76406c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI static constexpr bool __enable_explicit() { 7650b57cec5SDimitry Andric return !is_convertible<_QUp, _Tp>::value && 766*5f757f3fSDimitry Andric (is_same_v<remove_cv_t<_Tp>, bool> || !__check_constructible_from_opt<_Up>::value); 7670b57cec5SDimitry Andric } 7680b57cec5SDimitry Andric template <class _Up, class _QUp = _QualUp> 76906c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI static constexpr bool __enable_assign() { 770e8d8bef9SDimitry Andric // Construction and assignability of _QUp to _Tp has already been 7710b57cec5SDimitry Andric // checked. 7720b57cec5SDimitry Andric return !__check_constructible_from_opt<_Up>::value && 7730b57cec5SDimitry Andric !__check_assignable_from_opt<_Up>::value; 7740b57cec5SDimitry Andric } 7750b57cec5SDimitry Andric }; 7760b57cec5SDimitry Andric 7770b57cec5SDimitry Andric template <class _Up, class _QualUp> 7780b57cec5SDimitry Andric using _CheckOptionalLikeCtor = _If< 7790b57cec5SDimitry Andric _And< 7800b57cec5SDimitry Andric _IsNotSame<_Up, _Tp>, 7810b57cec5SDimitry Andric is_constructible<_Tp, _QualUp> 7820b57cec5SDimitry Andric >::value, 7830b57cec5SDimitry Andric _CheckOptionalLikeConstructor<_QualUp>, 7840b57cec5SDimitry Andric __check_tuple_constructor_fail 7850b57cec5SDimitry Andric >; 7860b57cec5SDimitry Andric template <class _Up, class _QualUp> 7870b57cec5SDimitry Andric using _CheckOptionalLikeAssign = _If< 7880b57cec5SDimitry Andric _And< 7890b57cec5SDimitry Andric _IsNotSame<_Up, _Tp>, 7900b57cec5SDimitry Andric is_constructible<_Tp, _QualUp>, 7910b57cec5SDimitry Andric is_assignable<_Tp&, _QualUp> 7920b57cec5SDimitry Andric >::value, 7930b57cec5SDimitry Andric _CheckOptionalLikeConstructor<_QualUp>, 7940b57cec5SDimitry Andric __check_tuple_constructor_fail 7950b57cec5SDimitry Andric >; 7960eae32dcSDimitry Andric 7970b57cec5SDimitry Andricpublic: 7980b57cec5SDimitry Andric 799*5f757f3fSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr optional() noexcept {} 800*5f757f3fSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr optional(const optional&) = default; 801*5f757f3fSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr optional(optional&&) = default; 802*5f757f3fSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr optional(nullopt_t) noexcept {} 8030b57cec5SDimitry Andric 804349cc55cSDimitry Andric template <class _InPlaceT, class... _Args, class = enable_if_t< 8050b57cec5SDimitry Andric _And< 8060b57cec5SDimitry Andric _IsSame<_InPlaceT, in_place_t>, 8070b57cec5SDimitry Andric is_constructible<value_type, _Args...> 8080b57cec5SDimitry Andric >::value 8090b57cec5SDimitry Andric > 8100b57cec5SDimitry Andric > 811*5f757f3fSDimitry Andric _LIBCPP_HIDE_FROM_ABI 8120b57cec5SDimitry Andric constexpr explicit optional(_InPlaceT, _Args&&... __args) 813*5f757f3fSDimitry Andric : __base(in_place, std::forward<_Args>(__args)...) {} 8140b57cec5SDimitry Andric 815349cc55cSDimitry Andric template <class _Up, class... _Args, class = enable_if_t< 8160b57cec5SDimitry Andric is_constructible_v<value_type, initializer_list<_Up>&, _Args...>> 8170b57cec5SDimitry Andric > 818*5f757f3fSDimitry Andric _LIBCPP_HIDE_FROM_ABI 8190b57cec5SDimitry Andric constexpr explicit optional(in_place_t, initializer_list<_Up> __il, _Args&&... __args) 820*5f757f3fSDimitry Andric : __base(in_place, __il, std::forward<_Args>(__args)...) {} 8210b57cec5SDimitry Andric 822349cc55cSDimitry Andric template <class _Up = value_type, enable_if_t< 8230b57cec5SDimitry Andric _CheckOptionalArgsCtor<_Up>::template __enable_implicit<_Up>() 8240b57cec5SDimitry Andric , int> = 0> 825*5f757f3fSDimitry Andric _LIBCPP_HIDE_FROM_ABI 8260b57cec5SDimitry Andric constexpr optional(_Up&& __v) 827*5f757f3fSDimitry Andric : __base(in_place, std::forward<_Up>(__v)) {} 8280b57cec5SDimitry Andric 829349cc55cSDimitry Andric template <class _Up, enable_if_t< 8300b57cec5SDimitry Andric _CheckOptionalArgsCtor<_Up>::template __enable_explicit<_Up>() 8310b57cec5SDimitry Andric , int> = 0> 832*5f757f3fSDimitry Andric _LIBCPP_HIDE_FROM_ABI 8330b57cec5SDimitry Andric constexpr explicit optional(_Up&& __v) 834*5f757f3fSDimitry Andric : __base(in_place, std::forward<_Up>(__v)) {} 8350b57cec5SDimitry Andric 8360b57cec5SDimitry Andric // LWG2756: conditionally explicit conversion from const optional<_Up>& 837349cc55cSDimitry Andric template <class _Up, enable_if_t< 8380b57cec5SDimitry Andric _CheckOptionalLikeCtor<_Up, _Up const&>::template __enable_implicit<_Up>() 8390b57cec5SDimitry Andric , int> = 0> 840*5f757f3fSDimitry Andric _LIBCPP_HIDE_FROM_ABI 841bdd1243dSDimitry Andric _LIBCPP_CONSTEXPR_SINCE_CXX20 optional(const optional<_Up>& __v) 8420b57cec5SDimitry Andric { 8430b57cec5SDimitry Andric this->__construct_from(__v); 8440b57cec5SDimitry Andric } 845349cc55cSDimitry Andric template <class _Up, enable_if_t< 8460b57cec5SDimitry Andric _CheckOptionalLikeCtor<_Up, _Up const&>::template __enable_explicit<_Up>() 8470b57cec5SDimitry Andric , int> = 0> 848*5f757f3fSDimitry Andric _LIBCPP_HIDE_FROM_ABI 849bdd1243dSDimitry Andric _LIBCPP_CONSTEXPR_SINCE_CXX20 explicit optional(const optional<_Up>& __v) 8500b57cec5SDimitry Andric { 8510b57cec5SDimitry Andric this->__construct_from(__v); 8520b57cec5SDimitry Andric } 8530b57cec5SDimitry Andric 8540b57cec5SDimitry Andric // LWG2756: conditionally explicit conversion from optional<_Up>&& 855349cc55cSDimitry Andric template <class _Up, enable_if_t< 8560b57cec5SDimitry Andric _CheckOptionalLikeCtor<_Up, _Up &&>::template __enable_implicit<_Up>() 8570b57cec5SDimitry Andric , int> = 0> 858*5f757f3fSDimitry Andric _LIBCPP_HIDE_FROM_ABI 859bdd1243dSDimitry Andric _LIBCPP_CONSTEXPR_SINCE_CXX20 optional(optional<_Up>&& __v) 8600b57cec5SDimitry Andric { 861*5f757f3fSDimitry Andric this->__construct_from(std::move(__v)); 8620b57cec5SDimitry Andric } 863349cc55cSDimitry Andric template <class _Up, enable_if_t< 8640b57cec5SDimitry Andric _CheckOptionalLikeCtor<_Up, _Up &&>::template __enable_explicit<_Up>() 8650b57cec5SDimitry Andric , int> = 0> 866*5f757f3fSDimitry Andric _LIBCPP_HIDE_FROM_ABI 867bdd1243dSDimitry Andric _LIBCPP_CONSTEXPR_SINCE_CXX20 explicit optional(optional<_Up>&& __v) 8680b57cec5SDimitry Andric { 869*5f757f3fSDimitry Andric this->__construct_from(std::move(__v)); 8700b57cec5SDimitry Andric } 8710b57cec5SDimitry Andric 87206c3fb27SDimitry Andric#if _LIBCPP_STD_VER >= 23 8730eae32dcSDimitry Andric template<class _Fp, class... _Args> 8740eae32dcSDimitry Andric _LIBCPP_HIDE_FROM_ABI 8750eae32dcSDimitry Andric constexpr explicit optional(__optional_construct_from_invoke_tag, _Fp&& __f, _Args&&... __args) 876*5f757f3fSDimitry Andric : __base(__optional_construct_from_invoke_tag{}, std::forward<_Fp>(__f), std::forward<_Args>(__args)...) { 8770eae32dcSDimitry Andric } 8780eae32dcSDimitry Andric#endif 8790eae32dcSDimitry Andric 880*5f757f3fSDimitry Andric _LIBCPP_HIDE_FROM_ABI 881bdd1243dSDimitry Andric _LIBCPP_CONSTEXPR_SINCE_CXX20 optional& operator=(nullopt_t) noexcept 8820b57cec5SDimitry Andric { 8830b57cec5SDimitry Andric reset(); 8840b57cec5SDimitry Andric return *this; 8850b57cec5SDimitry Andric } 8860b57cec5SDimitry Andric 88706c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr optional& operator=(const optional&) = default; 88806c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr optional& operator=(optional&&) = default; 8890b57cec5SDimitry Andric 8900b57cec5SDimitry Andric // LWG2756 8910b57cec5SDimitry Andric template <class _Up = value_type, 892349cc55cSDimitry Andric class = enable_if_t< 8930b57cec5SDimitry Andric _And< 894bdd1243dSDimitry Andric _IsNotSame<__remove_cvref_t<_Up>, optional>, 8950b57cec5SDimitry Andric _Or< 896bdd1243dSDimitry Andric _IsNotSame<__remove_cvref_t<_Up>, value_type>, 8970b57cec5SDimitry Andric _Not<is_scalar<value_type>> 8980b57cec5SDimitry Andric >, 8990b57cec5SDimitry Andric is_constructible<value_type, _Up>, 9000b57cec5SDimitry Andric is_assignable<value_type&, _Up> 9010b57cec5SDimitry Andric >::value> 9020b57cec5SDimitry Andric > 903*5f757f3fSDimitry Andric _LIBCPP_HIDE_FROM_ABI 904bdd1243dSDimitry Andric _LIBCPP_CONSTEXPR_SINCE_CXX20 optional& 9050b57cec5SDimitry Andric operator=(_Up&& __v) 9060b57cec5SDimitry Andric { 9070b57cec5SDimitry Andric if (this->has_value()) 908*5f757f3fSDimitry Andric this->__get() = std::forward<_Up>(__v); 9090b57cec5SDimitry Andric else 910*5f757f3fSDimitry Andric this->__construct(std::forward<_Up>(__v)); 9110b57cec5SDimitry Andric return *this; 9120b57cec5SDimitry Andric } 9130b57cec5SDimitry Andric 9140b57cec5SDimitry Andric // LWG2756 915349cc55cSDimitry Andric template <class _Up, enable_if_t< 9160b57cec5SDimitry Andric _CheckOptionalLikeAssign<_Up, _Up const&>::template __enable_assign<_Up>() 9170b57cec5SDimitry Andric , int> = 0> 918*5f757f3fSDimitry Andric _LIBCPP_HIDE_FROM_ABI 919bdd1243dSDimitry Andric _LIBCPP_CONSTEXPR_SINCE_CXX20 optional& 9200b57cec5SDimitry Andric operator=(const optional<_Up>& __v) 9210b57cec5SDimitry Andric { 9220b57cec5SDimitry Andric this->__assign_from(__v); 9230b57cec5SDimitry Andric return *this; 9240b57cec5SDimitry Andric } 9250b57cec5SDimitry Andric 9260b57cec5SDimitry Andric // LWG2756 927349cc55cSDimitry Andric template <class _Up, enable_if_t< 9280b57cec5SDimitry Andric _CheckOptionalLikeCtor<_Up, _Up &&>::template __enable_assign<_Up>() 9290b57cec5SDimitry Andric , int> = 0> 930*5f757f3fSDimitry Andric _LIBCPP_HIDE_FROM_ABI 931bdd1243dSDimitry Andric _LIBCPP_CONSTEXPR_SINCE_CXX20 optional& 9320b57cec5SDimitry Andric operator=(optional<_Up>&& __v) 9330b57cec5SDimitry Andric { 934*5f757f3fSDimitry Andric this->__assign_from(std::move(__v)); 9350b57cec5SDimitry Andric return *this; 9360b57cec5SDimitry Andric } 9370b57cec5SDimitry Andric 9380b57cec5SDimitry Andric template <class... _Args, 939349cc55cSDimitry Andric class = enable_if_t 9400b57cec5SDimitry Andric < 9410b57cec5SDimitry Andric is_constructible_v<value_type, _Args...> 9420b57cec5SDimitry Andric > 9430b57cec5SDimitry Andric > 944*5f757f3fSDimitry Andric _LIBCPP_HIDE_FROM_ABI 945bdd1243dSDimitry Andric _LIBCPP_CONSTEXPR_SINCE_CXX20 _Tp & 9460b57cec5SDimitry Andric emplace(_Args&&... __args) 9470b57cec5SDimitry Andric { 9480b57cec5SDimitry Andric reset(); 949*5f757f3fSDimitry Andric this->__construct(std::forward<_Args>(__args)...); 9500b57cec5SDimitry Andric return this->__get(); 9510b57cec5SDimitry Andric } 9520b57cec5SDimitry Andric 9530b57cec5SDimitry Andric template <class _Up, class... _Args, 954349cc55cSDimitry Andric class = enable_if_t 9550b57cec5SDimitry Andric < 9560b57cec5SDimitry Andric is_constructible_v<value_type, initializer_list<_Up>&, _Args...> 9570b57cec5SDimitry Andric > 9580b57cec5SDimitry Andric > 959*5f757f3fSDimitry Andric _LIBCPP_HIDE_FROM_ABI 960bdd1243dSDimitry Andric _LIBCPP_CONSTEXPR_SINCE_CXX20 _Tp & 9610b57cec5SDimitry Andric emplace(initializer_list<_Up> __il, _Args&&... __args) 9620b57cec5SDimitry Andric { 9630b57cec5SDimitry Andric reset(); 964*5f757f3fSDimitry Andric this->__construct(__il, std::forward<_Args>(__args)...); 9650b57cec5SDimitry Andric return this->__get(); 9660b57cec5SDimitry Andric } 9670b57cec5SDimitry Andric 968*5f757f3fSDimitry Andric _LIBCPP_HIDE_FROM_ABI 969bdd1243dSDimitry Andric _LIBCPP_CONSTEXPR_SINCE_CXX20 void swap(optional& __opt) 9700b57cec5SDimitry Andric noexcept(is_nothrow_move_constructible_v<value_type> && 9710b57cec5SDimitry Andric is_nothrow_swappable_v<value_type>) 9720b57cec5SDimitry Andric { 9730b57cec5SDimitry Andric if (this->has_value() == __opt.has_value()) 9740b57cec5SDimitry Andric { 975*5f757f3fSDimitry Andric using std::swap; 9760b57cec5SDimitry Andric if (this->has_value()) 9770b57cec5SDimitry Andric swap(this->__get(), __opt.__get()); 9780b57cec5SDimitry Andric } 9790b57cec5SDimitry Andric else 9800b57cec5SDimitry Andric { 9810b57cec5SDimitry Andric if (this->has_value()) 9820b57cec5SDimitry Andric { 983*5f757f3fSDimitry Andric __opt.__construct(std::move(this->__get())); 9840b57cec5SDimitry Andric reset(); 9850b57cec5SDimitry Andric } 9860b57cec5SDimitry Andric else 9870b57cec5SDimitry Andric { 988*5f757f3fSDimitry Andric this->__construct(std::move(__opt.__get())); 9890b57cec5SDimitry Andric __opt.reset(); 9900b57cec5SDimitry Andric } 9910b57cec5SDimitry Andric } 9920b57cec5SDimitry Andric } 9930b57cec5SDimitry Andric 994*5f757f3fSDimitry Andric _LIBCPP_HIDE_FROM_ABI 9950b57cec5SDimitry Andric constexpr 9960b57cec5SDimitry Andric add_pointer_t<value_type const> 9970b57cec5SDimitry Andric operator->() const 9980b57cec5SDimitry Andric { 99906c3fb27SDimitry Andric _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(this->has_value(), "optional operator-> called on a disengaged value"); 1000*5f757f3fSDimitry Andric return std::addressof(this->__get()); 10010b57cec5SDimitry Andric } 10020b57cec5SDimitry Andric 1003*5f757f3fSDimitry Andric _LIBCPP_HIDE_FROM_ABI 10040b57cec5SDimitry Andric constexpr 10050b57cec5SDimitry Andric add_pointer_t<value_type> 10060b57cec5SDimitry Andric operator->() 10070b57cec5SDimitry Andric { 100806c3fb27SDimitry Andric _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(this->has_value(), "optional operator-> called on a disengaged value"); 1009*5f757f3fSDimitry Andric return std::addressof(this->__get()); 10100b57cec5SDimitry Andric } 10110b57cec5SDimitry Andric 1012*5f757f3fSDimitry Andric _LIBCPP_HIDE_FROM_ABI 10130b57cec5SDimitry Andric constexpr 10140b57cec5SDimitry Andric const value_type& 1015fe6060f1SDimitry Andric operator*() const& noexcept 10160b57cec5SDimitry Andric { 101706c3fb27SDimitry Andric _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(this->has_value(), "optional operator* called on a disengaged value"); 10180b57cec5SDimitry Andric return this->__get(); 10190b57cec5SDimitry Andric } 10200b57cec5SDimitry Andric 1021*5f757f3fSDimitry Andric _LIBCPP_HIDE_FROM_ABI 10220b57cec5SDimitry Andric constexpr 10230b57cec5SDimitry Andric value_type& 1024fe6060f1SDimitry Andric operator*() & noexcept 10250b57cec5SDimitry Andric { 102606c3fb27SDimitry Andric _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(this->has_value(), "optional operator* called on a disengaged value"); 10270b57cec5SDimitry Andric return this->__get(); 10280b57cec5SDimitry Andric } 10290b57cec5SDimitry Andric 1030*5f757f3fSDimitry Andric _LIBCPP_HIDE_FROM_ABI 10310b57cec5SDimitry Andric constexpr 10320b57cec5SDimitry Andric value_type&& 1033fe6060f1SDimitry Andric operator*() && noexcept 10340b57cec5SDimitry Andric { 103506c3fb27SDimitry Andric _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(this->has_value(), "optional operator* called on a disengaged value"); 1036*5f757f3fSDimitry Andric return std::move(this->__get()); 10370b57cec5SDimitry Andric } 10380b57cec5SDimitry Andric 1039*5f757f3fSDimitry Andric _LIBCPP_HIDE_FROM_ABI 10400b57cec5SDimitry Andric constexpr 10410b57cec5SDimitry Andric const value_type&& 1042fe6060f1SDimitry Andric operator*() const&& noexcept 10430b57cec5SDimitry Andric { 104406c3fb27SDimitry Andric _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(this->has_value(), "optional operator* called on a disengaged value"); 1045*5f757f3fSDimitry Andric return std::move(this->__get()); 10460b57cec5SDimitry Andric } 10470b57cec5SDimitry Andric 1048*5f757f3fSDimitry Andric _LIBCPP_HIDE_FROM_ABI 10490b57cec5SDimitry Andric constexpr explicit operator bool() const noexcept { return has_value(); } 10500b57cec5SDimitry Andric 10510b57cec5SDimitry Andric using __base::has_value; 10520b57cec5SDimitry Andric using __base::__get; 10530b57cec5SDimitry Andric 1054*5f757f3fSDimitry Andric _LIBCPP_HIDE_FROM_ABI 10550b57cec5SDimitry Andric _LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS 10560b57cec5SDimitry Andric constexpr value_type const& value() const& 10570b57cec5SDimitry Andric { 10580b57cec5SDimitry Andric if (!this->has_value()) 10590b57cec5SDimitry Andric __throw_bad_optional_access(); 10600b57cec5SDimitry Andric return this->__get(); 10610b57cec5SDimitry Andric } 10620b57cec5SDimitry Andric 1063*5f757f3fSDimitry Andric _LIBCPP_HIDE_FROM_ABI 10640b57cec5SDimitry Andric _LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS 10650b57cec5SDimitry Andric constexpr value_type& value() & 10660b57cec5SDimitry Andric { 10670b57cec5SDimitry Andric if (!this->has_value()) 10680b57cec5SDimitry Andric __throw_bad_optional_access(); 10690b57cec5SDimitry Andric return this->__get(); 10700b57cec5SDimitry Andric } 10710b57cec5SDimitry Andric 1072*5f757f3fSDimitry Andric _LIBCPP_HIDE_FROM_ABI 10730b57cec5SDimitry Andric _LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS 10740b57cec5SDimitry Andric constexpr value_type&& value() && 10750b57cec5SDimitry Andric { 10760b57cec5SDimitry Andric if (!this->has_value()) 10770b57cec5SDimitry Andric __throw_bad_optional_access(); 1078*5f757f3fSDimitry Andric return std::move(this->__get()); 10790b57cec5SDimitry Andric } 10800b57cec5SDimitry Andric 1081*5f757f3fSDimitry Andric _LIBCPP_HIDE_FROM_ABI 10820b57cec5SDimitry Andric _LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS 10830b57cec5SDimitry Andric constexpr value_type const&& value() const&& 10840b57cec5SDimitry Andric { 10850b57cec5SDimitry Andric if (!this->has_value()) 10860b57cec5SDimitry Andric __throw_bad_optional_access(); 1087*5f757f3fSDimitry Andric return std::move(this->__get()); 10880b57cec5SDimitry Andric } 10890b57cec5SDimitry Andric 10900b57cec5SDimitry Andric template <class _Up> 1091*5f757f3fSDimitry Andric _LIBCPP_HIDE_FROM_ABI 10920b57cec5SDimitry Andric constexpr value_type value_or(_Up&& __v) const& 10930b57cec5SDimitry Andric { 10940b57cec5SDimitry Andric static_assert(is_copy_constructible_v<value_type>, 10950b57cec5SDimitry Andric "optional<T>::value_or: T must be copy constructible"); 10960b57cec5SDimitry Andric static_assert(is_convertible_v<_Up, value_type>, 10970b57cec5SDimitry Andric "optional<T>::value_or: U must be convertible to T"); 10980b57cec5SDimitry Andric return this->has_value() ? this->__get() : 1099*5f757f3fSDimitry Andric static_cast<value_type>(std::forward<_Up>(__v)); 11000b57cec5SDimitry Andric } 11010b57cec5SDimitry Andric 11020b57cec5SDimitry Andric template <class _Up> 1103*5f757f3fSDimitry Andric _LIBCPP_HIDE_FROM_ABI 11040b57cec5SDimitry Andric constexpr value_type value_or(_Up&& __v) && 11050b57cec5SDimitry Andric { 11060b57cec5SDimitry Andric static_assert(is_move_constructible_v<value_type>, 11070b57cec5SDimitry Andric "optional<T>::value_or: T must be move constructible"); 11080b57cec5SDimitry Andric static_assert(is_convertible_v<_Up, value_type>, 11090b57cec5SDimitry Andric "optional<T>::value_or: U must be convertible to T"); 1110*5f757f3fSDimitry Andric return this->has_value() ? std::move(this->__get()) : 1111*5f757f3fSDimitry Andric static_cast<value_type>(std::forward<_Up>(__v)); 11120b57cec5SDimitry Andric } 11130b57cec5SDimitry Andric 111406c3fb27SDimitry Andric#if _LIBCPP_STD_VER >= 23 11150eae32dcSDimitry Andric template<class _Func> 111681ad6265SDimitry Andric _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS 11170eae32dcSDimitry Andric constexpr auto and_then(_Func&& __f) & { 11180eae32dcSDimitry Andric using _Up = invoke_result_t<_Func, value_type&>; 11190eae32dcSDimitry Andric static_assert(__is_std_optional<remove_cvref_t<_Up>>::value, 11200eae32dcSDimitry Andric "Result of f(value()) must be a specialization of std::optional"); 11210eae32dcSDimitry Andric if (*this) 1122*5f757f3fSDimitry Andric return std::invoke(std::forward<_Func>(__f), value()); 11230eae32dcSDimitry Andric return remove_cvref_t<_Up>(); 11240eae32dcSDimitry Andric } 11250eae32dcSDimitry Andric 11260eae32dcSDimitry Andric template<class _Func> 112781ad6265SDimitry Andric _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS 11280eae32dcSDimitry Andric constexpr auto and_then(_Func&& __f) const& { 11290eae32dcSDimitry Andric using _Up = invoke_result_t<_Func, const value_type&>; 11300eae32dcSDimitry Andric static_assert(__is_std_optional<remove_cvref_t<_Up>>::value, 11310eae32dcSDimitry Andric "Result of f(value()) must be a specialization of std::optional"); 11320eae32dcSDimitry Andric if (*this) 1133*5f757f3fSDimitry Andric return std::invoke(std::forward<_Func>(__f), value()); 11340eae32dcSDimitry Andric return remove_cvref_t<_Up>(); 11350eae32dcSDimitry Andric } 11360eae32dcSDimitry Andric 11370eae32dcSDimitry Andric template<class _Func> 113881ad6265SDimitry Andric _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS 11390eae32dcSDimitry Andric constexpr auto and_then(_Func&& __f) && { 11400eae32dcSDimitry Andric using _Up = invoke_result_t<_Func, value_type&&>; 11410eae32dcSDimitry Andric static_assert(__is_std_optional<remove_cvref_t<_Up>>::value, 11420eae32dcSDimitry Andric "Result of f(std::move(value())) must be a specialization of std::optional"); 11430eae32dcSDimitry Andric if (*this) 1144*5f757f3fSDimitry Andric return std::invoke(std::forward<_Func>(__f), std::move(value())); 11450eae32dcSDimitry Andric return remove_cvref_t<_Up>(); 11460eae32dcSDimitry Andric } 11470eae32dcSDimitry Andric 11480eae32dcSDimitry Andric template<class _Func> 11490eae32dcSDimitry Andric _LIBCPP_HIDE_FROM_ABI 11500eae32dcSDimitry Andric constexpr auto and_then(_Func&& __f) const&& { 11510eae32dcSDimitry Andric using _Up = invoke_result_t<_Func, const value_type&&>; 11520eae32dcSDimitry Andric static_assert(__is_std_optional<remove_cvref_t<_Up>>::value, 11530eae32dcSDimitry Andric "Result of f(std::move(value())) must be a specialization of std::optional"); 11540eae32dcSDimitry Andric if (*this) 1155*5f757f3fSDimitry Andric return std::invoke(std::forward<_Func>(__f), std::move(value())); 11560eae32dcSDimitry Andric return remove_cvref_t<_Up>(); 11570eae32dcSDimitry Andric } 11580eae32dcSDimitry Andric 11590eae32dcSDimitry Andric template<class _Func> 116081ad6265SDimitry Andric _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS 11610eae32dcSDimitry Andric constexpr auto transform(_Func&& __f) & { 11620eae32dcSDimitry Andric using _Up = remove_cv_t<invoke_result_t<_Func, value_type&>>; 11630eae32dcSDimitry Andric static_assert(!is_array_v<_Up>, "Result of f(value()) should not be an Array"); 11640eae32dcSDimitry Andric static_assert(!is_same_v<_Up, in_place_t>, 11650eae32dcSDimitry Andric "Result of f(value()) should not be std::in_place_t"); 11660eae32dcSDimitry Andric static_assert(!is_same_v<_Up, nullopt_t>, 11670eae32dcSDimitry Andric "Result of f(value()) should not be std::nullopt_t"); 11680eae32dcSDimitry Andric static_assert(is_object_v<_Up>, "Result of f(value()) should be an object type"); 11690eae32dcSDimitry Andric if (*this) 1170*5f757f3fSDimitry Andric return optional<_Up>(__optional_construct_from_invoke_tag{}, std::forward<_Func>(__f), value()); 11710eae32dcSDimitry Andric return optional<_Up>(); 11720eae32dcSDimitry Andric } 11730eae32dcSDimitry Andric 11740eae32dcSDimitry Andric template<class _Func> 117581ad6265SDimitry Andric _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS 11760eae32dcSDimitry Andric constexpr auto transform(_Func&& __f) const& { 11770eae32dcSDimitry Andric using _Up = remove_cv_t<invoke_result_t<_Func, const value_type&>>; 11780eae32dcSDimitry Andric static_assert(!is_array_v<_Up>, "Result of f(value()) should not be an Array"); 11790eae32dcSDimitry Andric static_assert(!is_same_v<_Up, in_place_t>, 11800eae32dcSDimitry Andric "Result of f(value()) should not be std::in_place_t"); 11810eae32dcSDimitry Andric static_assert(!is_same_v<_Up, nullopt_t>, 11820eae32dcSDimitry Andric "Result of f(value()) should not be std::nullopt_t"); 11830eae32dcSDimitry Andric static_assert(is_object_v<_Up>, "Result of f(value()) should be an object type"); 11840eae32dcSDimitry Andric if (*this) 1185*5f757f3fSDimitry Andric return optional<_Up>(__optional_construct_from_invoke_tag{}, std::forward<_Func>(__f), value()); 11860eae32dcSDimitry Andric return optional<_Up>(); 11870eae32dcSDimitry Andric } 11880eae32dcSDimitry Andric 11890eae32dcSDimitry Andric template<class _Func> 119081ad6265SDimitry Andric _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS 11910eae32dcSDimitry Andric constexpr auto transform(_Func&& __f) && { 11920eae32dcSDimitry Andric using _Up = remove_cv_t<invoke_result_t<_Func, value_type&&>>; 11930eae32dcSDimitry Andric static_assert(!is_array_v<_Up>, "Result of f(std::move(value())) should not be an Array"); 11940eae32dcSDimitry Andric static_assert(!is_same_v<_Up, in_place_t>, 11950eae32dcSDimitry Andric "Result of f(std::move(value())) should not be std::in_place_t"); 11960eae32dcSDimitry Andric static_assert(!is_same_v<_Up, nullopt_t>, 11970eae32dcSDimitry Andric "Result of f(std::move(value())) should not be std::nullopt_t"); 11980eae32dcSDimitry Andric static_assert(is_object_v<_Up>, "Result of f(std::move(value())) should be an object type"); 11990eae32dcSDimitry Andric if (*this) 1200*5f757f3fSDimitry Andric return optional<_Up>(__optional_construct_from_invoke_tag{}, std::forward<_Func>(__f), std::move(value())); 12010eae32dcSDimitry Andric return optional<_Up>(); 12020eae32dcSDimitry Andric } 12030eae32dcSDimitry Andric 12040eae32dcSDimitry Andric template<class _Func> 120581ad6265SDimitry Andric _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS 12060eae32dcSDimitry Andric constexpr auto transform(_Func&& __f) const&& { 12070eae32dcSDimitry Andric using _Up = remove_cvref_t<invoke_result_t<_Func, const value_type&&>>; 12080eae32dcSDimitry Andric static_assert(!is_array_v<_Up>, "Result of f(std::move(value())) should not be an Array"); 12090eae32dcSDimitry Andric static_assert(!is_same_v<_Up, in_place_t>, 12100eae32dcSDimitry Andric "Result of f(std::move(value())) should not be std::in_place_t"); 12110eae32dcSDimitry Andric static_assert(!is_same_v<_Up, nullopt_t>, 12120eae32dcSDimitry Andric "Result of f(std::move(value())) should not be std::nullopt_t"); 12130eae32dcSDimitry Andric static_assert(is_object_v<_Up>, "Result of f(std::move(value())) should be an object type"); 12140eae32dcSDimitry Andric if (*this) 1215*5f757f3fSDimitry Andric return optional<_Up>(__optional_construct_from_invoke_tag{}, std::forward<_Func>(__f), std::move(value())); 12160eae32dcSDimitry Andric return optional<_Up>(); 12170eae32dcSDimitry Andric } 12180eae32dcSDimitry Andric 12190eae32dcSDimitry Andric template<invocable _Func> 12200eae32dcSDimitry Andric _LIBCPP_HIDE_FROM_ABI 12210eae32dcSDimitry Andric constexpr optional or_else(_Func&& __f) const& requires is_copy_constructible_v<value_type> { 12220eae32dcSDimitry Andric static_assert(is_same_v<remove_cvref_t<invoke_result_t<_Func>>, optional>, 12230eae32dcSDimitry Andric "Result of f() should be the same type as this optional"); 12240eae32dcSDimitry Andric if (*this) 12250eae32dcSDimitry Andric return *this; 1226*5f757f3fSDimitry Andric return std::forward<_Func>(__f)(); 12270eae32dcSDimitry Andric } 12280eae32dcSDimitry Andric 12290eae32dcSDimitry Andric template<invocable _Func> 12300eae32dcSDimitry Andric _LIBCPP_HIDE_FROM_ABI 12310eae32dcSDimitry Andric constexpr optional or_else(_Func&& __f) && requires is_move_constructible_v<value_type> { 12320eae32dcSDimitry Andric static_assert(is_same_v<remove_cvref_t<invoke_result_t<_Func>>, optional>, 12330eae32dcSDimitry Andric "Result of f() should be the same type as this optional"); 12340eae32dcSDimitry Andric if (*this) 1235*5f757f3fSDimitry Andric return std::move(*this); 1236*5f757f3fSDimitry Andric return std::forward<_Func>(__f)(); 12370eae32dcSDimitry Andric } 123806c3fb27SDimitry Andric#endif // _LIBCPP_STD_VER >= 23 12390eae32dcSDimitry Andric 12400b57cec5SDimitry Andric using __base::reset; 12410b57cec5SDimitry Andric}; 12420b57cec5SDimitry Andric 1243349cc55cSDimitry Andric#if _LIBCPP_STD_VER >= 17 124404eeddc0SDimitry Andrictemplate<class _Tp> 124504eeddc0SDimitry Andric optional(_Tp) -> optional<_Tp>; 12460b57cec5SDimitry Andric#endif 12470b57cec5SDimitry Andric 12480b57cec5SDimitry Andric// Comparisons between optionals 12490b57cec5SDimitry Andrictemplate <class _Tp, class _Up> 1250*5f757f3fSDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr 1251349cc55cSDimitry Andricenable_if_t< 1252bdd1243dSDimitry Andric is_convertible_v<decltype(std::declval<const _Tp&>() == 1253bdd1243dSDimitry 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) != static_cast<bool>(__y)) 12590b57cec5SDimitry Andric return false; 12600b57cec5SDimitry Andric if (!static_cast<bool>(__x)) 12610b57cec5SDimitry Andric return true; 12620b57cec5SDimitry Andric return *__x == *__y; 12630b57cec5SDimitry Andric} 12640b57cec5SDimitry Andric 12650b57cec5SDimitry Andrictemplate <class _Tp, class _Up> 1266*5f757f3fSDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr 1267349cc55cSDimitry Andricenable_if_t< 1268bdd1243dSDimitry Andric is_convertible_v<decltype(std::declval<const _Tp&>() != 1269bdd1243dSDimitry 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>(__x) != 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 Andrictemplate <class _Tp, class _Up> 1282*5f757f3fSDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr 1283349cc55cSDimitry Andricenable_if_t< 1284bdd1243dSDimitry Andric is_convertible_v<decltype(std::declval<const _Tp&>() < 1285bdd1243dSDimitry Andric std::declval<const _Up&>()), bool>, 12860b57cec5SDimitry Andric bool 12870b57cec5SDimitry Andric> 12880b57cec5SDimitry Andricoperator<(const optional<_Tp>& __x, const optional<_Up>& __y) 12890b57cec5SDimitry Andric{ 12900b57cec5SDimitry Andric if (!static_cast<bool>(__y)) 12910b57cec5SDimitry Andric return false; 12920b57cec5SDimitry Andric if (!static_cast<bool>(__x)) 12930b57cec5SDimitry Andric return true; 12940b57cec5SDimitry Andric return *__x < *__y; 12950b57cec5SDimitry Andric} 12960b57cec5SDimitry Andric 12970b57cec5SDimitry Andrictemplate <class _Tp, class _Up> 1298*5f757f3fSDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr 1299349cc55cSDimitry Andricenable_if_t< 1300bdd1243dSDimitry Andric is_convertible_v<decltype(std::declval<const _Tp&>() > 1301bdd1243dSDimitry Andric std::declval<const _Up&>()), bool>, 13020b57cec5SDimitry Andric bool 13030b57cec5SDimitry Andric> 13040b57cec5SDimitry Andricoperator>(const optional<_Tp>& __x, const optional<_Up>& __y) 13050b57cec5SDimitry Andric{ 13060b57cec5SDimitry Andric if (!static_cast<bool>(__x)) 13070b57cec5SDimitry Andric return false; 13080b57cec5SDimitry Andric if (!static_cast<bool>(__y)) 13090b57cec5SDimitry Andric return true; 13100b57cec5SDimitry Andric return *__x > *__y; 13110b57cec5SDimitry Andric} 13120b57cec5SDimitry Andric 13130b57cec5SDimitry Andrictemplate <class _Tp, class _Up> 1314*5f757f3fSDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr 1315349cc55cSDimitry Andricenable_if_t< 1316bdd1243dSDimitry Andric is_convertible_v<decltype(std::declval<const _Tp&>() <= 1317bdd1243dSDimitry Andric std::declval<const _Up&>()), bool>, 13180b57cec5SDimitry Andric bool 13190b57cec5SDimitry Andric> 13200b57cec5SDimitry Andricoperator<=(const optional<_Tp>& __x, const optional<_Up>& __y) 13210b57cec5SDimitry Andric{ 13220b57cec5SDimitry Andric if (!static_cast<bool>(__x)) 13230b57cec5SDimitry Andric return true; 13240b57cec5SDimitry Andric if (!static_cast<bool>(__y)) 13250b57cec5SDimitry Andric return false; 13260b57cec5SDimitry Andric return *__x <= *__y; 13270b57cec5SDimitry Andric} 13280b57cec5SDimitry Andric 13290b57cec5SDimitry Andrictemplate <class _Tp, class _Up> 1330*5f757f3fSDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr 1331349cc55cSDimitry Andricenable_if_t< 1332bdd1243dSDimitry Andric is_convertible_v<decltype(std::declval<const _Tp&>() >= 1333bdd1243dSDimitry Andric std::declval<const _Up&>()), bool>, 13340b57cec5SDimitry Andric bool 13350b57cec5SDimitry Andric> 13360b57cec5SDimitry Andricoperator>=(const optional<_Tp>& __x, const optional<_Up>& __y) 13370b57cec5SDimitry Andric{ 13380b57cec5SDimitry Andric if (!static_cast<bool>(__y)) 13390b57cec5SDimitry Andric return true; 13400b57cec5SDimitry Andric if (!static_cast<bool>(__x)) 13410b57cec5SDimitry Andric return false; 13420b57cec5SDimitry Andric return *__x >= *__y; 13430b57cec5SDimitry Andric} 13440b57cec5SDimitry Andric 134506c3fb27SDimitry Andric#if _LIBCPP_STD_VER >= 20 134606c3fb27SDimitry Andric 134706c3fb27SDimitry Andrictemplate <class _Tp, three_way_comparable_with<_Tp> _Up> 134806c3fb27SDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr compare_three_way_result_t<_Tp, _Up> 134906c3fb27SDimitry Andricoperator<=>(const optional<_Tp>& __x, const optional<_Up>& __y) { 135006c3fb27SDimitry Andric if (__x && __y) 135106c3fb27SDimitry Andric return *__x <=> *__y; 135206c3fb27SDimitry Andric return __x.has_value() <=> __y.has_value(); 135306c3fb27SDimitry Andric} 135406c3fb27SDimitry Andric 135506c3fb27SDimitry Andric#endif // _LIBCPP_STD_VER >= 20 135606c3fb27SDimitry Andric 13570b57cec5SDimitry Andric// Comparisons with nullopt 13580b57cec5SDimitry Andrictemplate <class _Tp> 1359*5f757f3fSDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr 13600b57cec5SDimitry Andricbool 13610b57cec5SDimitry Andricoperator==(const optional<_Tp>& __x, nullopt_t) noexcept 13620b57cec5SDimitry Andric{ 13630b57cec5SDimitry Andric return !static_cast<bool>(__x); 13640b57cec5SDimitry Andric} 13650b57cec5SDimitry Andric 136606c3fb27SDimitry Andric#if _LIBCPP_STD_VER <= 17 136706c3fb27SDimitry Andric 13680b57cec5SDimitry Andrictemplate <class _Tp> 1369*5f757f3fSDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr 13700b57cec5SDimitry Andricbool 13710b57cec5SDimitry Andricoperator==(nullopt_t, const optional<_Tp>& __x) noexcept 13720b57cec5SDimitry Andric{ 13730b57cec5SDimitry Andric return !static_cast<bool>(__x); 13740b57cec5SDimitry Andric} 13750b57cec5SDimitry Andric 13760b57cec5SDimitry Andrictemplate <class _Tp> 1377*5f757f3fSDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr 13780b57cec5SDimitry Andricbool 13790b57cec5SDimitry Andricoperator!=(const optional<_Tp>& __x, nullopt_t) noexcept 13800b57cec5SDimitry Andric{ 13810b57cec5SDimitry Andric return static_cast<bool>(__x); 13820b57cec5SDimitry Andric} 13830b57cec5SDimitry Andric 13840b57cec5SDimitry Andrictemplate <class _Tp> 1385*5f757f3fSDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr 13860b57cec5SDimitry Andricbool 13870b57cec5SDimitry Andricoperator!=(nullopt_t, const optional<_Tp>& __x) noexcept 13880b57cec5SDimitry Andric{ 13890b57cec5SDimitry Andric return static_cast<bool>(__x); 13900b57cec5SDimitry Andric} 13910b57cec5SDimitry Andric 13920b57cec5SDimitry Andrictemplate <class _Tp> 1393*5f757f3fSDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr 13940b57cec5SDimitry Andricbool 13950b57cec5SDimitry Andricoperator<(const optional<_Tp>&, nullopt_t) noexcept 13960b57cec5SDimitry Andric{ 13970b57cec5SDimitry Andric return false; 13980b57cec5SDimitry Andric} 13990b57cec5SDimitry Andric 14000b57cec5SDimitry Andrictemplate <class _Tp> 1401*5f757f3fSDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr 14020b57cec5SDimitry Andricbool 14030b57cec5SDimitry Andricoperator<(nullopt_t, const optional<_Tp>& __x) noexcept 14040b57cec5SDimitry Andric{ 14050b57cec5SDimitry Andric return static_cast<bool>(__x); 14060b57cec5SDimitry Andric} 14070b57cec5SDimitry Andric 14080b57cec5SDimitry Andrictemplate <class _Tp> 1409*5f757f3fSDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr 14100b57cec5SDimitry Andricbool 14110b57cec5SDimitry Andricoperator<=(const optional<_Tp>& __x, nullopt_t) noexcept 14120b57cec5SDimitry Andric{ 14130b57cec5SDimitry Andric return !static_cast<bool>(__x); 14140b57cec5SDimitry Andric} 14150b57cec5SDimitry Andric 14160b57cec5SDimitry Andrictemplate <class _Tp> 1417*5f757f3fSDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr 14180b57cec5SDimitry Andricbool 14190b57cec5SDimitry Andricoperator<=(nullopt_t, const optional<_Tp>&) noexcept 14200b57cec5SDimitry Andric{ 14210b57cec5SDimitry Andric return true; 14220b57cec5SDimitry Andric} 14230b57cec5SDimitry Andric 14240b57cec5SDimitry Andrictemplate <class _Tp> 1425*5f757f3fSDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr 14260b57cec5SDimitry Andricbool 14270b57cec5SDimitry Andricoperator>(const optional<_Tp>& __x, nullopt_t) noexcept 14280b57cec5SDimitry Andric{ 14290b57cec5SDimitry Andric return static_cast<bool>(__x); 14300b57cec5SDimitry Andric} 14310b57cec5SDimitry Andric 14320b57cec5SDimitry Andrictemplate <class _Tp> 1433*5f757f3fSDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr 14340b57cec5SDimitry Andricbool 14350b57cec5SDimitry Andricoperator>(nullopt_t, const optional<_Tp>&) noexcept 14360b57cec5SDimitry Andric{ 14370b57cec5SDimitry Andric return false; 14380b57cec5SDimitry Andric} 14390b57cec5SDimitry Andric 14400b57cec5SDimitry Andrictemplate <class _Tp> 1441*5f757f3fSDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr 14420b57cec5SDimitry Andricbool 14430b57cec5SDimitry Andricoperator>=(const optional<_Tp>&, nullopt_t) noexcept 14440b57cec5SDimitry Andric{ 14450b57cec5SDimitry Andric return true; 14460b57cec5SDimitry Andric} 14470b57cec5SDimitry Andric 14480b57cec5SDimitry Andrictemplate <class _Tp> 1449*5f757f3fSDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr 14500b57cec5SDimitry Andricbool 14510b57cec5SDimitry Andricoperator>=(nullopt_t, const optional<_Tp>& __x) noexcept 14520b57cec5SDimitry Andric{ 14530b57cec5SDimitry Andric return !static_cast<bool>(__x); 14540b57cec5SDimitry Andric} 14550b57cec5SDimitry Andric 145606c3fb27SDimitry Andric#else // _LIBCPP_STD_VER <= 17 145706c3fb27SDimitry Andric 145806c3fb27SDimitry Andrictemplate <class _Tp> 145906c3fb27SDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr strong_ordering operator<=>(const optional<_Tp>& __x, nullopt_t) noexcept { 146006c3fb27SDimitry Andric return __x.has_value() <=> false; 146106c3fb27SDimitry Andric} 146206c3fb27SDimitry Andric 146306c3fb27SDimitry Andric#endif // _LIBCPP_STD_VER <= 17 146406c3fb27SDimitry Andric 14650b57cec5SDimitry Andric// Comparisons with T 14660b57cec5SDimitry Andrictemplate <class _Tp, class _Up> 1467*5f757f3fSDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr 1468349cc55cSDimitry Andricenable_if_t< 1469bdd1243dSDimitry Andric is_convertible_v<decltype(std::declval<const _Tp&>() == 1470bdd1243dSDimitry Andric std::declval<const _Up&>()), bool>, 14710b57cec5SDimitry Andric bool 14720b57cec5SDimitry Andric> 14730b57cec5SDimitry Andricoperator==(const optional<_Tp>& __x, const _Up& __v) 14740b57cec5SDimitry Andric{ 14750b57cec5SDimitry Andric return static_cast<bool>(__x) ? *__x == __v : false; 14760b57cec5SDimitry Andric} 14770b57cec5SDimitry Andric 14780b57cec5SDimitry Andrictemplate <class _Tp, class _Up> 1479*5f757f3fSDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr 1480349cc55cSDimitry Andricenable_if_t< 1481bdd1243dSDimitry Andric is_convertible_v<decltype(std::declval<const _Tp&>() == 1482bdd1243dSDimitry Andric std::declval<const _Up&>()), bool>, 14830b57cec5SDimitry Andric bool 14840b57cec5SDimitry Andric> 14850b57cec5SDimitry Andricoperator==(const _Tp& __v, const optional<_Up>& __x) 14860b57cec5SDimitry Andric{ 14870b57cec5SDimitry Andric return static_cast<bool>(__x) ? __v == *__x : false; 14880b57cec5SDimitry Andric} 14890b57cec5SDimitry Andric 14900b57cec5SDimitry Andrictemplate <class _Tp, class _Up> 1491*5f757f3fSDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr 1492349cc55cSDimitry Andricenable_if_t< 1493bdd1243dSDimitry Andric is_convertible_v<decltype(std::declval<const _Tp&>() != 1494bdd1243dSDimitry Andric std::declval<const _Up&>()), bool>, 14950b57cec5SDimitry Andric bool 14960b57cec5SDimitry Andric> 14970b57cec5SDimitry Andricoperator!=(const optional<_Tp>& __x, const _Up& __v) 14980b57cec5SDimitry Andric{ 14990b57cec5SDimitry Andric return static_cast<bool>(__x) ? *__x != __v : true; 15000b57cec5SDimitry Andric} 15010b57cec5SDimitry Andric 15020b57cec5SDimitry Andrictemplate <class _Tp, class _Up> 1503*5f757f3fSDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr 1504349cc55cSDimitry Andricenable_if_t< 1505bdd1243dSDimitry Andric is_convertible_v<decltype(std::declval<const _Tp&>() != 1506bdd1243dSDimitry Andric std::declval<const _Up&>()), bool>, 15070b57cec5SDimitry Andric bool 15080b57cec5SDimitry Andric> 15090b57cec5SDimitry Andricoperator!=(const _Tp& __v, const optional<_Up>& __x) 15100b57cec5SDimitry Andric{ 15110b57cec5SDimitry Andric return static_cast<bool>(__x) ? __v != *__x : true; 15120b57cec5SDimitry Andric} 15130b57cec5SDimitry Andric 15140b57cec5SDimitry Andrictemplate <class _Tp, class _Up> 1515*5f757f3fSDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr 1516349cc55cSDimitry Andricenable_if_t< 1517bdd1243dSDimitry Andric is_convertible_v<decltype(std::declval<const _Tp&>() < 1518bdd1243dSDimitry Andric std::declval<const _Up&>()), bool>, 15190b57cec5SDimitry Andric bool 15200b57cec5SDimitry Andric> 15210b57cec5SDimitry Andricoperator<(const optional<_Tp>& __x, const _Up& __v) 15220b57cec5SDimitry Andric{ 15230b57cec5SDimitry Andric return static_cast<bool>(__x) ? *__x < __v : true; 15240b57cec5SDimitry Andric} 15250b57cec5SDimitry Andric 15260b57cec5SDimitry Andrictemplate <class _Tp, class _Up> 1527*5f757f3fSDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr 1528349cc55cSDimitry Andricenable_if_t< 1529bdd1243dSDimitry Andric is_convertible_v<decltype(std::declval<const _Tp&>() < 1530bdd1243dSDimitry Andric std::declval<const _Up&>()), bool>, 15310b57cec5SDimitry Andric bool 15320b57cec5SDimitry Andric> 15330b57cec5SDimitry Andricoperator<(const _Tp& __v, const optional<_Up>& __x) 15340b57cec5SDimitry Andric{ 15350b57cec5SDimitry Andric return static_cast<bool>(__x) ? __v < *__x : false; 15360b57cec5SDimitry Andric} 15370b57cec5SDimitry Andric 15380b57cec5SDimitry Andrictemplate <class _Tp, class _Up> 1539*5f757f3fSDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr 1540349cc55cSDimitry Andricenable_if_t< 1541bdd1243dSDimitry Andric is_convertible_v<decltype(std::declval<const _Tp&>() <= 1542bdd1243dSDimitry Andric std::declval<const _Up&>()), bool>, 15430b57cec5SDimitry Andric bool 15440b57cec5SDimitry Andric> 15450b57cec5SDimitry Andricoperator<=(const optional<_Tp>& __x, const _Up& __v) 15460b57cec5SDimitry Andric{ 15470b57cec5SDimitry Andric return static_cast<bool>(__x) ? *__x <= __v : true; 15480b57cec5SDimitry Andric} 15490b57cec5SDimitry Andric 15500b57cec5SDimitry Andrictemplate <class _Tp, class _Up> 1551*5f757f3fSDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr 1552349cc55cSDimitry Andricenable_if_t< 1553bdd1243dSDimitry Andric is_convertible_v<decltype(std::declval<const _Tp&>() <= 1554bdd1243dSDimitry Andric std::declval<const _Up&>()), bool>, 15550b57cec5SDimitry Andric bool 15560b57cec5SDimitry Andric> 15570b57cec5SDimitry Andricoperator<=(const _Tp& __v, const optional<_Up>& __x) 15580b57cec5SDimitry Andric{ 15590b57cec5SDimitry Andric return static_cast<bool>(__x) ? __v <= *__x : false; 15600b57cec5SDimitry Andric} 15610b57cec5SDimitry Andric 15620b57cec5SDimitry Andrictemplate <class _Tp, class _Up> 1563*5f757f3fSDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr 1564349cc55cSDimitry Andricenable_if_t< 1565bdd1243dSDimitry Andric is_convertible_v<decltype(std::declval<const _Tp&>() > 1566bdd1243dSDimitry Andric std::declval<const _Up&>()), bool>, 15670b57cec5SDimitry Andric bool 15680b57cec5SDimitry Andric> 15690b57cec5SDimitry Andricoperator>(const optional<_Tp>& __x, const _Up& __v) 15700b57cec5SDimitry Andric{ 15710b57cec5SDimitry Andric return static_cast<bool>(__x) ? *__x > __v : false; 15720b57cec5SDimitry Andric} 15730b57cec5SDimitry Andric 15740b57cec5SDimitry Andrictemplate <class _Tp, class _Up> 1575*5f757f3fSDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr 1576349cc55cSDimitry Andricenable_if_t< 1577bdd1243dSDimitry Andric is_convertible_v<decltype(std::declval<const _Tp&>() > 1578bdd1243dSDimitry Andric std::declval<const _Up&>()), bool>, 15790b57cec5SDimitry Andric bool 15800b57cec5SDimitry Andric> 15810b57cec5SDimitry Andricoperator>(const _Tp& __v, const optional<_Up>& __x) 15820b57cec5SDimitry Andric{ 15830b57cec5SDimitry Andric return static_cast<bool>(__x) ? __v > *__x : true; 15840b57cec5SDimitry Andric} 15850b57cec5SDimitry Andric 15860b57cec5SDimitry Andrictemplate <class _Tp, class _Up> 1587*5f757f3fSDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr 1588349cc55cSDimitry Andricenable_if_t< 1589bdd1243dSDimitry Andric is_convertible_v<decltype(std::declval<const _Tp&>() >= 1590bdd1243dSDimitry Andric std::declval<const _Up&>()), bool>, 15910b57cec5SDimitry Andric bool 15920b57cec5SDimitry Andric> 15930b57cec5SDimitry Andricoperator>=(const optional<_Tp>& __x, const _Up& __v) 15940b57cec5SDimitry Andric{ 15950b57cec5SDimitry Andric return static_cast<bool>(__x) ? *__x >= __v : false; 15960b57cec5SDimitry Andric} 15970b57cec5SDimitry Andric 15980b57cec5SDimitry Andrictemplate <class _Tp, class _Up> 1599*5f757f3fSDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr 1600349cc55cSDimitry Andricenable_if_t< 1601bdd1243dSDimitry Andric is_convertible_v<decltype(std::declval<const _Tp&>() >= 1602bdd1243dSDimitry Andric std::declval<const _Up&>()), bool>, 16030b57cec5SDimitry Andric bool 16040b57cec5SDimitry Andric> 16050b57cec5SDimitry Andricoperator>=(const _Tp& __v, const optional<_Up>& __x) 16060b57cec5SDimitry Andric{ 16070b57cec5SDimitry Andric return static_cast<bool>(__x) ? __v >= *__x : true; 16080b57cec5SDimitry Andric} 16090b57cec5SDimitry Andric 161006c3fb27SDimitry Andric#if _LIBCPP_STD_VER >= 20 161106c3fb27SDimitry Andric 161206c3fb27SDimitry Andrictemplate <class _Tp, class _Up> 161306c3fb27SDimitry Andric requires(!__is_derived_from_optional<_Up>) && three_way_comparable_with<_Tp, _Up> 161406c3fb27SDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr compare_three_way_result_t<_Tp, _Up> 161506c3fb27SDimitry Andricoperator<=>(const optional<_Tp>& __x, const _Up& __v) { 161606c3fb27SDimitry Andric return __x.has_value() ? *__x <=> __v : strong_ordering::less; 161706c3fb27SDimitry Andric} 161806c3fb27SDimitry Andric 161906c3fb27SDimitry Andric#endif // _LIBCPP_STD_VER >= 20 162006c3fb27SDimitry Andric 16210b57cec5SDimitry Andric 16220b57cec5SDimitry Andrictemplate <class _Tp> 1623*5f757f3fSDimitry Andricinline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 1624349cc55cSDimitry Andricenable_if_t< 16250b57cec5SDimitry Andric is_move_constructible_v<_Tp> && is_swappable_v<_Tp>, 16260b57cec5SDimitry Andric void 16270b57cec5SDimitry Andric> 16280b57cec5SDimitry Andricswap(optional<_Tp>& __x, optional<_Tp>& __y) noexcept(noexcept(__x.swap(__y))) 16290b57cec5SDimitry Andric{ 16300b57cec5SDimitry Andric __x.swap(__y); 16310b57cec5SDimitry Andric} 16320b57cec5SDimitry Andric 16330b57cec5SDimitry Andrictemplate <class _Tp> 1634*5f757f3fSDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr 16350b57cec5SDimitry Andricoptional<decay_t<_Tp>> make_optional(_Tp&& __v) 16360b57cec5SDimitry Andric{ 1637*5f757f3fSDimitry Andric return optional<decay_t<_Tp>>(std::forward<_Tp>(__v)); 16380b57cec5SDimitry Andric} 16390b57cec5SDimitry Andric 16400b57cec5SDimitry Andrictemplate <class _Tp, class... _Args> 1641*5f757f3fSDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr 16420b57cec5SDimitry Andricoptional<_Tp> make_optional(_Args&&... __args) 16430b57cec5SDimitry Andric{ 1644*5f757f3fSDimitry Andric return optional<_Tp>(in_place, std::forward<_Args>(__args)...); 16450b57cec5SDimitry Andric} 16460b57cec5SDimitry Andric 16470b57cec5SDimitry Andrictemplate <class _Tp, class _Up, class... _Args> 1648*5f757f3fSDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr 16490b57cec5SDimitry Andricoptional<_Tp> make_optional(initializer_list<_Up> __il, _Args&&... __args) 16500b57cec5SDimitry Andric{ 1651*5f757f3fSDimitry Andric return optional<_Tp>(in_place, __il, std::forward<_Args>(__args)...); 16520b57cec5SDimitry Andric} 16530b57cec5SDimitry Andric 16540b57cec5SDimitry Andrictemplate <class _Tp> 16550b57cec5SDimitry Andricstruct _LIBCPP_TEMPLATE_VIS hash< 16560b57cec5SDimitry Andric __enable_hash_helper<optional<_Tp>, remove_const_t<_Tp>> 16570b57cec5SDimitry Andric> 16580b57cec5SDimitry Andric{ 1659fe6060f1SDimitry Andric#if _LIBCPP_STD_VER <= 17 || defined(_LIBCPP_ENABLE_CXX20_REMOVED_BINDER_TYPEDEFS) 1660fe6060f1SDimitry Andric _LIBCPP_DEPRECATED_IN_CXX17 typedef optional<_Tp> argument_type; 1661fe6060f1SDimitry Andric _LIBCPP_DEPRECATED_IN_CXX17 typedef size_t result_type; 1662fe6060f1SDimitry Andric#endif 16630b57cec5SDimitry Andric 1664*5f757f3fSDimitry Andric _LIBCPP_HIDE_FROM_ABI 1665fe6060f1SDimitry Andric size_t operator()(const optional<_Tp>& __opt) const 16660b57cec5SDimitry Andric { 16670b57cec5SDimitry Andric return static_cast<bool>(__opt) ? hash<remove_const_t<_Tp>>()(*__opt) : 0; 16680b57cec5SDimitry Andric } 16690b57cec5SDimitry Andric}; 16700b57cec5SDimitry Andric 16710b57cec5SDimitry Andric_LIBCPP_END_NAMESPACE_STD 16720b57cec5SDimitry Andric 167306c3fb27SDimitry Andric#endif // _LIBCPP_STD_VER >= 17 167406c3fb27SDimitry Andric 167506c3fb27SDimitry Andric_LIBCPP_POP_MACROS 16760b57cec5SDimitry Andric 1677bdd1243dSDimitry Andric#if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER <= 20 1678bdd1243dSDimitry Andric# include <atomic> 1679bdd1243dSDimitry Andric# include <climits> 1680bdd1243dSDimitry Andric# include <concepts> 1681bdd1243dSDimitry Andric# include <ctime> 1682bdd1243dSDimitry Andric# include <iterator> 1683bdd1243dSDimitry Andric# include <memory> 1684bdd1243dSDimitry Andric# include <ratio> 1685*5f757f3fSDimitry Andric# include <stdexcept> 1686bdd1243dSDimitry Andric# include <tuple> 168706c3fb27SDimitry Andric# include <type_traits> 1688bdd1243dSDimitry Andric# include <typeinfo> 1689bdd1243dSDimitry Andric# include <utility> 1690bdd1243dSDimitry Andric# include <variant> 1691bdd1243dSDimitry Andric#endif 1692bdd1243dSDimitry Andric 16930b57cec5SDimitry Andric#endif // _LIBCPP_OPTIONAL 1694