1a9e65961SEric Fiselier// -*- C++ -*- 2eb8650a7SLouis Dionne//===----------------------------------------------------------------------===// 3a9e65961SEric Fiselier// 457b08b09SChandler Carruth// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 557b08b09SChandler Carruth// See https://llvm.org/LICENSE.txt for license information. 657b08b09SChandler Carruth// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 7a9e65961SEric Fiselier// 8a9e65961SEric Fiselier//===----------------------------------------------------------------------===// 9a9e65961SEric Fiselier 10a9e65961SEric Fiselier#ifndef _LIBCPP_OPTIONAL 11a9e65961SEric Fiselier#define _LIBCPP_OPTIONAL 12a9e65961SEric Fiselier 13a9e65961SEric Fiselier/* 14a9e65961SEric Fiselier optional synopsis 15a9e65961SEric Fiselier 16a9e65961SEric Fiselier// C++1z 17a9e65961SEric Fiselier 18a9e65961SEric Fiseliernamespace std { 19e3bdfe63SCasey Carter // 23.6.3, optional for object types 20a9e65961SEric Fiselier template <class T> class optional; 21a9e65961SEric Fiselier 22e3bdfe63SCasey Carter // 23.6.4, no-value state indicator 23a9e65961SEric Fiselier struct nullopt_t{see below }; 2440a01d53SMarshall Clow inline constexpr nullopt_t nullopt(unspecified ); 25a9e65961SEric Fiselier 26e3bdfe63SCasey Carter // 23.6.5, class bad_optional_access 27a9e65961SEric Fiselier class bad_optional_access; 28a9e65961SEric Fiselier 29e3bdfe63SCasey Carter // 23.6.6, relational operators 30e3bdfe63SCasey Carter template <class T, class U> 31e3bdfe63SCasey Carter constexpr bool operator==(const optional<T>&, const optional<U>&); 32e3bdfe63SCasey Carter template <class T, class U> 33e3bdfe63SCasey Carter constexpr bool operator!=(const optional<T>&, const optional<U>&); 34e3bdfe63SCasey Carter template <class T, class U> 35e3bdfe63SCasey Carter constexpr bool operator<(const optional<T>&, const optional<U>&); 36e3bdfe63SCasey Carter template <class T, class U> 37e3bdfe63SCasey Carter constexpr bool operator>(const optional<T>&, const optional<U>&); 38e3bdfe63SCasey Carter template <class T, class U> 39e3bdfe63SCasey Carter constexpr bool operator<=(const optional<T>&, const optional<U>&); 40e3bdfe63SCasey Carter template <class T, class U> 41e3bdfe63SCasey Carter constexpr bool operator>=(const optional<T>&, const optional<U>&); 42e3bdfe63SCasey Carter 43e3bdfe63SCasey Carter // 23.6.7 comparison with nullopt 44a9e65961SEric Fiselier template <class T> constexpr bool operator==(const optional<T>&, nullopt_t) noexcept; 45a9e65961SEric Fiselier template <class T> constexpr bool operator==(nullopt_t, const optional<T>&) noexcept; 46a9e65961SEric Fiselier template <class T> constexpr bool operator!=(const optional<T>&, nullopt_t) noexcept; 47a9e65961SEric Fiselier template <class T> constexpr bool operator!=(nullopt_t, const optional<T>&) noexcept; 48a9e65961SEric Fiselier template <class T> constexpr bool operator<(const optional<T>&, nullopt_t) noexcept; 49a9e65961SEric Fiselier template <class T> constexpr bool operator<(nullopt_t, const optional<T>&) noexcept; 50a9e65961SEric Fiselier template <class T> constexpr bool operator<=(const optional<T>&, nullopt_t) noexcept; 51a9e65961SEric Fiselier template <class T> constexpr bool operator<=(nullopt_t, const optional<T>&) noexcept; 52a9e65961SEric Fiselier template <class T> constexpr bool operator>(const optional<T>&, nullopt_t) noexcept; 53a9e65961SEric Fiselier template <class T> constexpr bool operator>(nullopt_t, const optional<T>&) noexcept; 54a9e65961SEric Fiselier template <class T> constexpr bool operator>=(const optional<T>&, nullopt_t) noexcept; 55a9e65961SEric Fiselier template <class T> constexpr bool operator>=(nullopt_t, const optional<T>&) noexcept; 56a9e65961SEric Fiselier 57e3bdfe63SCasey Carter // 23.6.8, comparison with T 58e3bdfe63SCasey Carter template <class T, class U> constexpr bool operator==(const optional<T>&, const U&); 5913e6e61bSMarshall Clow template <class T, class U> constexpr bool operator==(const T&, const optional<U>&); 60e3bdfe63SCasey Carter template <class T, class U> constexpr bool operator!=(const optional<T>&, const U&); 6113e6e61bSMarshall Clow template <class T, class U> constexpr bool operator!=(const T&, const optional<U>&); 62e3bdfe63SCasey Carter template <class T, class U> constexpr bool operator<(const optional<T>&, const U&); 6313e6e61bSMarshall Clow template <class T, class U> constexpr bool operator<(const T&, const optional<U>&); 64e3bdfe63SCasey Carter template <class T, class U> constexpr bool operator<=(const optional<T>&, const U&); 6513e6e61bSMarshall Clow template <class T, class U> constexpr bool operator<=(const T&, const optional<U>&); 66e3bdfe63SCasey Carter template <class T, class U> constexpr bool operator>(const optional<T>&, const U&); 6713e6e61bSMarshall Clow template <class T, class U> constexpr bool operator>(const T&, const optional<U>&); 68e3bdfe63SCasey Carter template <class T, class U> constexpr bool operator>=(const optional<T>&, const U&); 6913e6e61bSMarshall Clow template <class T, class U> constexpr bool operator>=(const T&, const optional<U>&); 70a9e65961SEric Fiselier 71e3bdfe63SCasey Carter // 23.6.9, specialized algorithms 7254644993SChristopher Di Bella template <class T> void swap(optional<T>&, optional<T>&) noexcept(see below ); // constexpr in C++20 73a9e65961SEric Fiselier template <class T> constexpr optional<see below > make_optional(T&&); 74a9e65961SEric Fiselier template <class T, class... Args> 75a9e65961SEric Fiselier constexpr optional<T> make_optional(Args&&... args); 76a9e65961SEric Fiselier template <class T, class U, class... Args> 77a9e65961SEric Fiselier constexpr optional<T> make_optional(initializer_list<U> il, Args&&... args); 78a9e65961SEric Fiselier 79e3bdfe63SCasey Carter // 23.6.10, hash support 80a9e65961SEric Fiselier template <class T> struct hash; 81a9e65961SEric Fiselier template <class T> struct hash<optional<T>>; 82a9e65961SEric Fiselier 83a9e65961SEric Fiselier template <class T> class optional { 84a9e65961SEric Fiselier public: 85a9e65961SEric Fiselier using value_type = T; 86a9e65961SEric Fiselier 87e3bdfe63SCasey Carter // 23.6.3.1, constructors 88a9e65961SEric Fiselier constexpr optional() noexcept; 89a9e65961SEric Fiselier constexpr optional(nullopt_t) noexcept; 90a9e65961SEric Fiselier optional(const optional &); 91a9e65961SEric Fiselier optional(optional &&) noexcept(see below); 92a9e65961SEric Fiselier template <class... Args> constexpr explicit optional(in_place_t, Args &&...); 93a9e65961SEric Fiselier template <class U, class... Args> 94a9e65961SEric Fiselier constexpr explicit optional(in_place_t, initializer_list<U>, Args &&...); 95a9e65961SEric Fiselier template <class U = T> 969e5c2934SMark de Wever constexpr explicit(see-below) optional(U &&); 97a9e65961SEric Fiselier template <class U> 989e5c2934SMark de Wever explicit(see-below) optional(const optional<U> &); // constexpr in C++20 99a9e65961SEric Fiselier template <class U> 1009e5c2934SMark de Wever explicit(see-below) optional(optional<U> &&); // constexpr in C++20 101a9e65961SEric Fiselier 102e3bdfe63SCasey Carter // 23.6.3.2, destructor 10354644993SChristopher Di Bella ~optional(); // constexpr in C++20 104a9e65961SEric Fiselier 105e3bdfe63SCasey Carter // 23.6.3.3, assignment 10654644993SChristopher Di Bella optional &operator=(nullopt_t) noexcept; // constexpr in C++20 1071d5f6a81SLouis Dionne optional &operator=(const optional &); // constexpr in C++20 1081d5f6a81SLouis Dionne optional &operator=(optional &&) noexcept(see below); // constexpr in C++20 10954644993SChristopher Di Bella template <class U = T> optional &operator=(U &&); // constexpr in C++20 11054644993SChristopher Di Bella template <class U> optional &operator=(const optional<U> &); // constexpr in C++20 11154644993SChristopher Di Bella template <class U> optional &operator=(optional<U> &&); // constexpr in C++20 11254644993SChristopher Di Bella template <class... Args> T& emplace(Args &&...); // constexpr in C++20 113a9e65961SEric Fiselier template <class U, class... Args> 11454644993SChristopher Di Bella T& emplace(initializer_list<U>, Args &&...); // constexpr in C++20 115a9e65961SEric Fiselier 116e3bdfe63SCasey Carter // 23.6.3.4, swap 11754644993SChristopher Di Bella void swap(optional &) noexcept(see below ); // constexpr in C++20 118a9e65961SEric Fiselier 119e3bdfe63SCasey Carter // 23.6.3.5, observers 120a9e65961SEric Fiselier constexpr T const *operator->() const; 121a9e65961SEric Fiselier constexpr T *operator->(); 122a9e65961SEric Fiselier constexpr T const &operator*() const &; 123a9e65961SEric Fiselier constexpr T &operator*() &; 124a9e65961SEric Fiselier constexpr T &&operator*() &&; 125a9e65961SEric Fiselier constexpr const T &&operator*() const &&; 126a9e65961SEric Fiselier constexpr explicit operator bool() const noexcept; 127a9e65961SEric Fiselier constexpr bool has_value() const noexcept; 128a9e65961SEric Fiselier constexpr T const &value() const &; 129a9e65961SEric Fiselier constexpr T &value() &; 130a9e65961SEric Fiselier constexpr T &&value() &&; 131a9e65961SEric Fiselier constexpr const T &&value() const &&; 132a9e65961SEric Fiselier template <class U> constexpr T value_or(U &&) const &; 133a9e65961SEric Fiselier template <class U> constexpr T value_or(U &&) &&; 134a9e65961SEric Fiselier 13517cfc57dSNikolas Klauser // [optional.monadic], monadic operations 13617cfc57dSNikolas Klauser template<class F> constexpr auto and_then(F&& f) &; // since C++23 13717cfc57dSNikolas Klauser template<class F> constexpr auto and_then(F&& f) &&; // since C++23 13817cfc57dSNikolas Klauser template<class F> constexpr auto and_then(F&& f) const&; // since C++23 13917cfc57dSNikolas Klauser template<class F> constexpr auto and_then(F&& f) const&&; // since C++23 14017cfc57dSNikolas Klauser template<class F> constexpr auto transform(F&& f) &; // since C++23 14117cfc57dSNikolas Klauser template<class F> constexpr auto transform(F&& f) &&; // since C++23 14217cfc57dSNikolas Klauser template<class F> constexpr auto transform(F&& f) const&; // since C++23 14317cfc57dSNikolas Klauser template<class F> constexpr auto transform(F&& f) const&&; // since C++23 14417cfc57dSNikolas Klauser template<class F> constexpr optional or_else(F&& f) &&; // since C++23 14517cfc57dSNikolas Klauser template<class F> constexpr optional or_else(F&& f) const&; // since C++23 14617cfc57dSNikolas Klauser 147e3bdfe63SCasey Carter // 23.6.3.6, modifiers 14854644993SChristopher Di Bella void reset() noexcept; // constexpr in C++20 149a9e65961SEric Fiselier 150a9e65961SEric Fiselier private: 151a9e65961SEric Fiselier T *val; // exposition only 152a9e65961SEric Fiselier }; 153f35b4bc3SMarshall Clow 154f35b4bc3SMarshall Clowtemplate<class T> 155f35b4bc3SMarshall Clow optional(T) -> optional<T>; 156f35b4bc3SMarshall Clow 157a9e65961SEric Fiselier} // namespace std 158a9e65961SEric Fiselier 159a9e65961SEric Fiselier*/ 160a9e65961SEric Fiselier 161385cc25aSLouis Dionne#include <__assert> // all public C++ headers provide the assertion handler 1622eadbc86SLouis Dionne#include <__availability> 16317cfc57dSNikolas Klauser#include <__concepts/invocable.h> 164bfbd73f8SArthur O'Dwyer#include <__config> 165faef447eSNikolas Klauser#include <__functional/hash.h> 166faef447eSNikolas Klauser#include <__functional/invoke.h> 167faef447eSNikolas Klauser#include <__functional/unary_function.h> 168faef447eSNikolas Klauser#include <__memory/construct_at.h> 169faef447eSNikolas Klauser#include <__tuple> 170faef447eSNikolas Klauser#include <__utility/forward.h> 17152915d78SNikolas Klauser#include <__utility/in_place.h> 172faef447eSNikolas Klauser#include <__utility/move.h> 17352915d78SNikolas Klauser#include <__utility/swap.h> 174a9e65961SEric Fiselier#include <initializer_list> 175a9e65961SEric Fiselier#include <new> 176a9e65961SEric Fiselier#include <stdexcept> 177a9e65961SEric Fiselier#include <type_traits> 178f56972e2SMarshall Clow#include <version> 179a9e65961SEric Fiselier 180*de4a57cbSLouis Dionne#ifndef _LIBCPP_REMOVE_TRANSITIVE_INCLUDES 181*de4a57cbSLouis Dionne# include <atomic> 182*de4a57cbSLouis Dionne# include <chrono> 183*de4a57cbSLouis Dionne# include <climits> 184*de4a57cbSLouis Dionne# include <concepts> 185*de4a57cbSLouis Dionne# include <ctime> 186*de4a57cbSLouis Dionne# include <iterator> 187*de4a57cbSLouis Dionne# include <memory> 188*de4a57cbSLouis Dionne# include <ratio> 189*de4a57cbSLouis Dionne# include <tuple> 190*de4a57cbSLouis Dionne# include <typeinfo> 191*de4a57cbSLouis Dionne# include <utility> 192*de4a57cbSLouis Dionne# include <variant> 193*de4a57cbSLouis Dionne#endif 194*de4a57cbSLouis Dionne 195db1978b6SNikolas Klauser// standard-mandated includes 196db1978b6SNikolas Klauser#include <compare> 197db1978b6SNikolas Klauser 198a9e65961SEric Fiselier#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 199a9e65961SEric Fiselier# pragma GCC system_header 200a9e65961SEric Fiselier#endif 201a9e65961SEric Fiselier 202a9e65961SEric Fiseliernamespace std // purposefully not using versioning namespace 203a9e65961SEric Fiselier{ 204a9e65961SEric Fiselier 2058a063df1SLouis Dionneclass _LIBCPP_EXCEPTION_ABI _LIBCPP_AVAILABILITY_BAD_OPTIONAL_ACCESS bad_optional_access 206e29b1ed5SMarshall Clow : public exception 207a9e65961SEric Fiselier{ 208a9e65961SEric Fiselierpublic: 209a9e65961SEric Fiselier // Get the key function ~bad_optional_access() into the dylib 2106a1d0785SMarshall Clow virtual ~bad_optional_access() _NOEXCEPT; 211e29b1ed5SMarshall Clow virtual const char* what() const _NOEXCEPT; 212a9e65961SEric Fiselier}; 213a9e65961SEric Fiselier 214d2b0df35SNikolas Klauser} // namespace std 215a9e65961SEric Fiselier 216a9e65961SEric Fiselier#if _LIBCPP_STD_VER > 14 217a9e65961SEric Fiselier 218a9e65961SEric Fiselier_LIBCPP_BEGIN_NAMESPACE_STD 219a9e65961SEric Fiselier 220a9e65961SEric Fiselier_LIBCPP_NORETURN 221a9e65961SEric Fiselierinline _LIBCPP_INLINE_VISIBILITY 2228a063df1SLouis Dionne_LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS 223a9e65961SEric Fiseliervoid __throw_bad_optional_access() { 224a9e65961SEric Fiselier#ifndef _LIBCPP_NO_EXCEPTIONS 225a9e65961SEric Fiselier throw bad_optional_access(); 226a9e65961SEric Fiselier#else 227a9e65961SEric Fiselier _VSTD::abort(); 228a9e65961SEric Fiselier#endif 229a9e65961SEric Fiselier} 230a9e65961SEric Fiselier 231a9e65961SEric Fiselierstruct nullopt_t 232a9e65961SEric Fiselier{ 233a9e65961SEric Fiselier struct __secret_tag { _LIBCPP_INLINE_VISIBILITY explicit __secret_tag() = default; }; 234a9e65961SEric Fiselier _LIBCPP_INLINE_VISIBILITY constexpr explicit nullopt_t(__secret_tag, __secret_tag) noexcept {} 235a9e65961SEric Fiselier}; 236a9e65961SEric Fiselier 237cb793e1aSLouis Dionneinline constexpr nullopt_t nullopt{nullopt_t::__secret_tag{}, nullopt_t::__secret_tag{}}; 238a9e65961SEric Fiselier 23917cfc57dSNikolas Klauserstruct __optional_construct_from_invoke_tag {}; 24017cfc57dSNikolas Klauser 241a9e65961SEric Fiseliertemplate <class _Tp, bool = is_trivially_destructible<_Tp>::value> 242a9e65961SEric Fiselierstruct __optional_destruct_base; 243a9e65961SEric Fiselier 244a9e65961SEric Fiseliertemplate <class _Tp> 245a9e65961SEric Fiselierstruct __optional_destruct_base<_Tp, false> 246a9e65961SEric Fiselier{ 247a9e65961SEric Fiselier typedef _Tp value_type; 248a9e65961SEric Fiselier static_assert(is_object_v<value_type>, 249a9e65961SEric Fiselier "instantiation of optional with a non-object type is undefined behavior"); 250a9e65961SEric Fiselier union 251a9e65961SEric Fiselier { 252a9e65961SEric Fiselier char __null_state_; 253a9e65961SEric Fiselier value_type __val_; 254a9e65961SEric Fiselier }; 255a9e65961SEric Fiselier bool __engaged_; 256a9e65961SEric Fiselier 257a9e65961SEric Fiselier _LIBCPP_INLINE_VISIBILITY 25854644993SChristopher Di Bella _LIBCPP_CONSTEXPR_AFTER_CXX17 ~__optional_destruct_base() 259a9e65961SEric Fiselier { 260a9e65961SEric Fiselier if (__engaged_) 261a9e65961SEric Fiselier __val_.~value_type(); 262a9e65961SEric Fiselier } 263a9e65961SEric Fiselier 264a9e65961SEric Fiselier _LIBCPP_INLINE_VISIBILITY 265a9e65961SEric Fiselier constexpr __optional_destruct_base() noexcept 266a9e65961SEric Fiselier : __null_state_(), 267a9e65961SEric Fiselier __engaged_(false) {} 268a9e65961SEric Fiselier 269a9e65961SEric Fiselier template <class... _Args> 270a9e65961SEric Fiselier _LIBCPP_INLINE_VISIBILITY 271a9e65961SEric Fiselier constexpr explicit __optional_destruct_base(in_place_t, _Args&&... __args) 272a9e65961SEric Fiselier : __val_(_VSTD::forward<_Args>(__args)...), 273a9e65961SEric Fiselier __engaged_(true) {} 274a9e65961SEric Fiselier 27517cfc57dSNikolas Klauser#if _LIBCPP_STD_VER > 20 27617cfc57dSNikolas Klauser template <class _Fp, class... _Args> 27717cfc57dSNikolas Klauser _LIBCPP_HIDE_FROM_ABI 27817cfc57dSNikolas Klauser constexpr __optional_destruct_base(__optional_construct_from_invoke_tag, _Fp&& __f, _Args&&... __args) 27917cfc57dSNikolas Klauser : __val_(_VSTD::invoke(_VSTD::forward<_Fp>(__f), _VSTD::forward<_Args>(__args)...)), __engaged_(true) {} 28017cfc57dSNikolas Klauser#endif 28117cfc57dSNikolas Klauser 282a9e65961SEric Fiselier _LIBCPP_INLINE_VISIBILITY 28354644993SChristopher Di Bella _LIBCPP_CONSTEXPR_AFTER_CXX17 void reset() noexcept 284a9e65961SEric Fiselier { 285a9e65961SEric Fiselier if (__engaged_) 286a9e65961SEric Fiselier { 287a9e65961SEric Fiselier __val_.~value_type(); 288a9e65961SEric Fiselier __engaged_ = false; 289a9e65961SEric Fiselier } 290a9e65961SEric Fiselier } 291a9e65961SEric Fiselier}; 292a9e65961SEric Fiselier 293a9e65961SEric Fiseliertemplate <class _Tp> 294a9e65961SEric Fiselierstruct __optional_destruct_base<_Tp, true> 295a9e65961SEric Fiselier{ 296a9e65961SEric Fiselier typedef _Tp value_type; 297a9e65961SEric Fiselier static_assert(is_object_v<value_type>, 298a9e65961SEric Fiselier "instantiation of optional with a non-object type is undefined behavior"); 299a9e65961SEric Fiselier union 300a9e65961SEric Fiselier { 301a9e65961SEric Fiselier char __null_state_; 302a9e65961SEric Fiselier value_type __val_; 303a9e65961SEric Fiselier }; 304a9e65961SEric Fiselier bool __engaged_; 305a9e65961SEric Fiselier 306a9e65961SEric Fiselier _LIBCPP_INLINE_VISIBILITY 307a9e65961SEric Fiselier constexpr __optional_destruct_base() noexcept 308a9e65961SEric Fiselier : __null_state_(), 309a9e65961SEric Fiselier __engaged_(false) {} 310a9e65961SEric Fiselier 311a9e65961SEric Fiselier template <class... _Args> 312a9e65961SEric Fiselier _LIBCPP_INLINE_VISIBILITY 313a9e65961SEric Fiselier constexpr explicit __optional_destruct_base(in_place_t, _Args&&... __args) 314a9e65961SEric Fiselier : __val_(_VSTD::forward<_Args>(__args)...), 315a9e65961SEric Fiselier __engaged_(true) {} 316a9e65961SEric Fiselier 31717cfc57dSNikolas Klauser#if _LIBCPP_STD_VER > 20 31817cfc57dSNikolas Klauser template <class _Fp, class... _Args> 31917cfc57dSNikolas Klauser _LIBCPP_HIDE_FROM_ABI 32017cfc57dSNikolas Klauser constexpr __optional_destruct_base(__optional_construct_from_invoke_tag, _Fp&& __f, _Args&&... __args) 32117cfc57dSNikolas Klauser : __val_(_VSTD::invoke(_VSTD::forward<_Fp>(__f), _VSTD::forward<_Args>(__args)...)), __engaged_(true) {} 32217cfc57dSNikolas Klauser#endif 32317cfc57dSNikolas Klauser 324a9e65961SEric Fiselier _LIBCPP_INLINE_VISIBILITY 32554644993SChristopher Di Bella _LIBCPP_CONSTEXPR_AFTER_CXX17 void reset() noexcept 326a9e65961SEric Fiselier { 327a9e65961SEric Fiselier if (__engaged_) 328a9e65961SEric Fiselier { 329a9e65961SEric Fiselier __engaged_ = false; 330a9e65961SEric Fiselier } 331a9e65961SEric Fiselier } 332a9e65961SEric Fiselier}; 333a9e65961SEric Fiselier 334a9e65961SEric Fiseliertemplate <class _Tp, bool = is_reference<_Tp>::value> 335a9e65961SEric Fiselierstruct __optional_storage_base : __optional_destruct_base<_Tp> 336a9e65961SEric Fiselier{ 337a9e65961SEric Fiselier using __base = __optional_destruct_base<_Tp>; 338a9e65961SEric Fiselier using value_type = _Tp; 339a9e65961SEric Fiselier using __base::__base; 340a9e65961SEric Fiselier 341a9e65961SEric Fiselier _LIBCPP_INLINE_VISIBILITY 342a9e65961SEric Fiselier constexpr bool has_value() const noexcept 343a9e65961SEric Fiselier { 344a9e65961SEric Fiselier return this->__engaged_; 345a9e65961SEric Fiselier } 346a9e65961SEric Fiselier 347a9e65961SEric Fiselier _LIBCPP_INLINE_VISIBILITY 348a9e65961SEric Fiselier constexpr value_type& __get() & noexcept 349a9e65961SEric Fiselier { 350a9e65961SEric Fiselier return this->__val_; 351a9e65961SEric Fiselier } 352a9e65961SEric Fiselier _LIBCPP_INLINE_VISIBILITY 353a9e65961SEric Fiselier constexpr const value_type& __get() const& noexcept 354a9e65961SEric Fiselier { 355a9e65961SEric Fiselier return this->__val_; 356a9e65961SEric Fiselier } 357a9e65961SEric Fiselier _LIBCPP_INLINE_VISIBILITY 358a9e65961SEric Fiselier constexpr value_type&& __get() && noexcept 359a9e65961SEric Fiselier { 360a9e65961SEric Fiselier return _VSTD::move(this->__val_); 361a9e65961SEric Fiselier } 362a9e65961SEric Fiselier _LIBCPP_INLINE_VISIBILITY 363a9e65961SEric Fiselier constexpr const value_type&& __get() const&& noexcept 364a9e65961SEric Fiselier { 365a9e65961SEric Fiselier return _VSTD::move(this->__val_); 366a9e65961SEric Fiselier } 367a9e65961SEric Fiselier 368a9e65961SEric Fiselier template <class... _Args> 369a9e65961SEric Fiselier _LIBCPP_INLINE_VISIBILITY 37054644993SChristopher Di Bella _LIBCPP_CONSTEXPR_AFTER_CXX17 void __construct(_Args&&... __args) 371a9e65961SEric Fiselier { 372a9e65961SEric Fiselier _LIBCPP_ASSERT(!has_value(), "__construct called for engaged __optional_storage"); 37354644993SChristopher Di Bella#if _LIBCPP_STD_VER > 17 37454644993SChristopher Di Bella _VSTD::construct_at(_VSTD::addressof(this->__val_), _VSTD::forward<_Args>(__args)...); 37554644993SChristopher Di Bella#else 376a9e65961SEric Fiselier ::new ((void*)_VSTD::addressof(this->__val_)) value_type(_VSTD::forward<_Args>(__args)...); 37754644993SChristopher Di Bella#endif 378a9e65961SEric Fiselier this->__engaged_ = true; 379a9e65961SEric Fiselier } 380a9e65961SEric Fiselier 381a9e65961SEric Fiselier template <class _That> 382a9e65961SEric Fiselier _LIBCPP_INLINE_VISIBILITY 38354644993SChristopher Di Bella _LIBCPP_CONSTEXPR_AFTER_CXX17 void __construct_from(_That&& __opt) 384a9e65961SEric Fiselier { 385a9e65961SEric Fiselier if (__opt.has_value()) 386a9e65961SEric Fiselier __construct(_VSTD::forward<_That>(__opt).__get()); 387a9e65961SEric Fiselier } 388a9e65961SEric Fiselier 389a9e65961SEric Fiselier template <class _That> 390a9e65961SEric Fiselier _LIBCPP_INLINE_VISIBILITY 39154644993SChristopher Di Bella _LIBCPP_CONSTEXPR_AFTER_CXX17 void __assign_from(_That&& __opt) 392a9e65961SEric Fiselier { 393a9e65961SEric Fiselier if (this->__engaged_ == __opt.has_value()) 394a9e65961SEric Fiselier { 395a9e65961SEric Fiselier if (this->__engaged_) 396a9e65961SEric Fiselier this->__val_ = _VSTD::forward<_That>(__opt).__get(); 397a9e65961SEric Fiselier } 398a9e65961SEric Fiselier else 399a9e65961SEric Fiselier { 400a9e65961SEric Fiselier if (this->__engaged_) 401a9e65961SEric Fiselier this->reset(); 402a9e65961SEric Fiselier else 403a9e65961SEric Fiselier __construct(_VSTD::forward<_That>(__opt).__get()); 404a9e65961SEric Fiselier } 405a9e65961SEric Fiselier } 406a9e65961SEric Fiselier}; 407a9e65961SEric Fiselier 4087b291b6fSWill Hawkins// optional<T&> is currently required to be ill-formed. However, it may 4097b291b6fSWill Hawkins// be allowed in the future. For this reason, it has already been implemented 4107b291b6fSWill Hawkins// to ensure we can make the change in an ABI-compatible manner. 411a9e65961SEric Fiseliertemplate <class _Tp> 412a9e65961SEric Fiselierstruct __optional_storage_base<_Tp, true> 413a9e65961SEric Fiselier{ 414a9e65961SEric Fiselier using value_type = _Tp; 415a9e65961SEric Fiselier using __raw_type = remove_reference_t<_Tp>; 416a9e65961SEric Fiselier __raw_type* __value_; 417a9e65961SEric Fiselier 418a9e65961SEric Fiselier template <class _Up> 419a9e65961SEric Fiselier static constexpr bool __can_bind_reference() { 420a9e65961SEric Fiselier using _RawUp = typename remove_reference<_Up>::type; 421a9e65961SEric Fiselier using _UpPtr = _RawUp*; 422a9e65961SEric Fiselier using _RawTp = typename remove_reference<_Tp>::type; 423a9e65961SEric Fiselier using _TpPtr = _RawTp*; 424a9e65961SEric Fiselier using _CheckLValueArg = integral_constant<bool, 425a9e65961SEric Fiselier (is_lvalue_reference<_Up>::value && is_convertible<_UpPtr, _TpPtr>::value) 426a9e65961SEric Fiselier || is_same<_RawUp, reference_wrapper<_RawTp>>::value 427a9e65961SEric Fiselier || is_same<_RawUp, reference_wrapper<typename remove_const<_RawTp>::type>>::value 428a9e65961SEric Fiselier >; 429a9e65961SEric Fiselier return (is_lvalue_reference<_Tp>::value && _CheckLValueArg::value) 430a9e65961SEric Fiselier || (is_rvalue_reference<_Tp>::value && !is_lvalue_reference<_Up>::value && 431a9e65961SEric Fiselier is_convertible<_UpPtr, _TpPtr>::value); 432a9e65961SEric Fiselier } 433a9e65961SEric Fiselier 434a9e65961SEric Fiselier _LIBCPP_INLINE_VISIBILITY 435a9e65961SEric Fiselier constexpr __optional_storage_base() noexcept 436a9e65961SEric Fiselier : __value_(nullptr) {} 437a9e65961SEric Fiselier 438a9e65961SEric Fiselier template <class _UArg> 439a9e65961SEric Fiselier _LIBCPP_INLINE_VISIBILITY 440a9e65961SEric Fiselier constexpr explicit __optional_storage_base(in_place_t, _UArg&& __uarg) 441a9e65961SEric Fiselier : __value_(_VSTD::addressof(__uarg)) 442a9e65961SEric Fiselier { 443a9e65961SEric Fiselier static_assert(__can_bind_reference<_UArg>(), 444a9e65961SEric Fiselier "Attempted to construct a reference element in tuple from a " 445a9e65961SEric Fiselier "possible temporary"); 446a9e65961SEric Fiselier } 447a9e65961SEric Fiselier 448a9e65961SEric Fiselier _LIBCPP_INLINE_VISIBILITY 44954644993SChristopher Di Bella _LIBCPP_CONSTEXPR_AFTER_CXX17 void reset() noexcept { __value_ = nullptr; } 450a9e65961SEric Fiselier 451a9e65961SEric Fiselier _LIBCPP_INLINE_VISIBILITY 452a9e65961SEric Fiselier constexpr bool has_value() const noexcept 453a9e65961SEric Fiselier { return __value_ != nullptr; } 454a9e65961SEric Fiselier 455a9e65961SEric Fiselier _LIBCPP_INLINE_VISIBILITY 456a9e65961SEric Fiselier constexpr value_type& __get() const& noexcept 457a9e65961SEric Fiselier { return *__value_; } 458a9e65961SEric Fiselier 459a9e65961SEric Fiselier _LIBCPP_INLINE_VISIBILITY 460a9e65961SEric Fiselier constexpr value_type&& __get() const&& noexcept 461a9e65961SEric Fiselier { return _VSTD::forward<value_type>(*__value_); } 462a9e65961SEric Fiselier 463a9e65961SEric Fiselier template <class _UArg> 464a9e65961SEric Fiselier _LIBCPP_INLINE_VISIBILITY 46554644993SChristopher Di Bella _LIBCPP_CONSTEXPR_AFTER_CXX17 void __construct(_UArg&& __val) 466a9e65961SEric Fiselier { 467a9e65961SEric Fiselier _LIBCPP_ASSERT(!has_value(), "__construct called for engaged __optional_storage"); 468a9e65961SEric Fiselier static_assert(__can_bind_reference<_UArg>(), 469a9e65961SEric Fiselier "Attempted to construct a reference element in tuple from a " 470a9e65961SEric Fiselier "possible temporary"); 471a9e65961SEric Fiselier __value_ = _VSTD::addressof(__val); 472a9e65961SEric Fiselier } 473a9e65961SEric Fiselier 474a9e65961SEric Fiselier template <class _That> 475a9e65961SEric Fiselier _LIBCPP_INLINE_VISIBILITY 47654644993SChristopher Di Bella _LIBCPP_CONSTEXPR_AFTER_CXX17 void __construct_from(_That&& __opt) 477a9e65961SEric Fiselier { 478a9e65961SEric Fiselier if (__opt.has_value()) 479a9e65961SEric Fiselier __construct(_VSTD::forward<_That>(__opt).__get()); 480a9e65961SEric Fiselier } 481a9e65961SEric Fiselier 482a9e65961SEric Fiselier template <class _That> 483a9e65961SEric Fiselier _LIBCPP_INLINE_VISIBILITY 48454644993SChristopher Di Bella _LIBCPP_CONSTEXPR_AFTER_CXX17 void __assign_from(_That&& __opt) 485a9e65961SEric Fiselier { 486a9e65961SEric Fiselier if (has_value() == __opt.has_value()) 487a9e65961SEric Fiselier { 488a9e65961SEric Fiselier if (has_value()) 489a9e65961SEric Fiselier *__value_ = _VSTD::forward<_That>(__opt).__get(); 490a9e65961SEric Fiselier } 491a9e65961SEric Fiselier else 492a9e65961SEric Fiselier { 493a9e65961SEric Fiselier if (has_value()) 494a9e65961SEric Fiselier reset(); 495a9e65961SEric Fiselier else 496a9e65961SEric Fiselier __construct(_VSTD::forward<_That>(__opt).__get()); 497a9e65961SEric Fiselier } 498a9e65961SEric Fiselier } 499a9e65961SEric Fiselier}; 500a9e65961SEric Fiselier 501f2d571c8SCasey Cartertemplate <class _Tp, bool = is_trivially_copy_constructible<_Tp>::value> 502f2d571c8SCasey Carterstruct __optional_copy_base : __optional_storage_base<_Tp> 503a9e65961SEric Fiselier{ 504a9e65961SEric Fiselier using __optional_storage_base<_Tp>::__optional_storage_base; 505a9e65961SEric Fiselier}; 506a9e65961SEric Fiselier 507a9e65961SEric Fiseliertemplate <class _Tp> 508f2d571c8SCasey Carterstruct __optional_copy_base<_Tp, false> : __optional_storage_base<_Tp> 509a9e65961SEric Fiselier{ 510a9e65961SEric Fiselier using __optional_storage_base<_Tp>::__optional_storage_base; 511a9e65961SEric Fiselier 512a9e65961SEric Fiselier _LIBCPP_INLINE_VISIBILITY 513f2d571c8SCasey Carter __optional_copy_base() = default; 514a9e65961SEric Fiselier 515a9e65961SEric Fiselier _LIBCPP_INLINE_VISIBILITY 51654644993SChristopher Di Bella _LIBCPP_CONSTEXPR_AFTER_CXX17 __optional_copy_base(const __optional_copy_base& __opt) 517a9e65961SEric Fiselier { 518a9e65961SEric Fiselier this->__construct_from(__opt); 519a9e65961SEric Fiselier } 520a9e65961SEric Fiselier 521a9e65961SEric Fiselier _LIBCPP_INLINE_VISIBILITY 522f2d571c8SCasey Carter __optional_copy_base(__optional_copy_base&&) = default; 523f2d571c8SCasey Carter _LIBCPP_INLINE_VISIBILITY 524f2d571c8SCasey Carter __optional_copy_base& operator=(const __optional_copy_base&) = default; 525f2d571c8SCasey Carter _LIBCPP_INLINE_VISIBILITY 526f2d571c8SCasey Carter __optional_copy_base& operator=(__optional_copy_base&&) = default; 527f2d571c8SCasey Carter}; 528f2d571c8SCasey Carter 529f2d571c8SCasey Cartertemplate <class _Tp, bool = is_trivially_move_constructible<_Tp>::value> 530f2d571c8SCasey Carterstruct __optional_move_base : __optional_copy_base<_Tp> 531f2d571c8SCasey Carter{ 532f2d571c8SCasey Carter using __optional_copy_base<_Tp>::__optional_copy_base; 533f2d571c8SCasey Carter}; 534f2d571c8SCasey Carter 535f2d571c8SCasey Cartertemplate <class _Tp> 536f2d571c8SCasey Carterstruct __optional_move_base<_Tp, false> : __optional_copy_base<_Tp> 537f2d571c8SCasey Carter{ 538f2d571c8SCasey Carter using value_type = _Tp; 539f2d571c8SCasey Carter using __optional_copy_base<_Tp>::__optional_copy_base; 540f2d571c8SCasey Carter 541f2d571c8SCasey Carter _LIBCPP_INLINE_VISIBILITY 542f2d571c8SCasey Carter __optional_move_base() = default; 543f2d571c8SCasey Carter _LIBCPP_INLINE_VISIBILITY 544f2d571c8SCasey Carter __optional_move_base(const __optional_move_base&) = default; 545f2d571c8SCasey Carter 546f2d571c8SCasey Carter _LIBCPP_INLINE_VISIBILITY 54754644993SChristopher Di Bella _LIBCPP_CONSTEXPR_AFTER_CXX17 __optional_move_base(__optional_move_base&& __opt) 548a9e65961SEric Fiselier noexcept(is_nothrow_move_constructible_v<value_type>) 549a9e65961SEric Fiselier { 550a9e65961SEric Fiselier this->__construct_from(_VSTD::move(__opt)); 551a9e65961SEric Fiselier } 552a9e65961SEric Fiselier 553a9e65961SEric Fiselier _LIBCPP_INLINE_VISIBILITY 554f2d571c8SCasey Carter __optional_move_base& operator=(const __optional_move_base&) = default; 555f2d571c8SCasey Carter _LIBCPP_INLINE_VISIBILITY 556f2d571c8SCasey Carter __optional_move_base& operator=(__optional_move_base&&) = default; 557f2d571c8SCasey Carter}; 558f2d571c8SCasey Carter 559f2d571c8SCasey Cartertemplate <class _Tp, bool = 560f2d571c8SCasey Carter is_trivially_destructible<_Tp>::value && 561f2d571c8SCasey Carter is_trivially_copy_constructible<_Tp>::value && 562f2d571c8SCasey Carter is_trivially_copy_assignable<_Tp>::value> 563f2d571c8SCasey Carterstruct __optional_copy_assign_base : __optional_move_base<_Tp> 564f2d571c8SCasey Carter{ 565f2d571c8SCasey Carter using __optional_move_base<_Tp>::__optional_move_base; 566f2d571c8SCasey Carter}; 567f2d571c8SCasey Carter 568f2d571c8SCasey Cartertemplate <class _Tp> 569f2d571c8SCasey Carterstruct __optional_copy_assign_base<_Tp, false> : __optional_move_base<_Tp> 570f2d571c8SCasey Carter{ 571f2d571c8SCasey Carter using __optional_move_base<_Tp>::__optional_move_base; 572f2d571c8SCasey Carter 573f2d571c8SCasey Carter _LIBCPP_INLINE_VISIBILITY 574f2d571c8SCasey Carter __optional_copy_assign_base() = default; 575f2d571c8SCasey Carter _LIBCPP_INLINE_VISIBILITY 576f2d571c8SCasey Carter __optional_copy_assign_base(const __optional_copy_assign_base&) = default; 577f2d571c8SCasey Carter _LIBCPP_INLINE_VISIBILITY 578f2d571c8SCasey Carter __optional_copy_assign_base(__optional_copy_assign_base&&) = default; 579f2d571c8SCasey Carter 580f2d571c8SCasey Carter _LIBCPP_INLINE_VISIBILITY 58154644993SChristopher Di Bella _LIBCPP_CONSTEXPR_AFTER_CXX17 __optional_copy_assign_base& operator=(const __optional_copy_assign_base& __opt) 582a9e65961SEric Fiselier { 583a9e65961SEric Fiselier this->__assign_from(__opt); 584a9e65961SEric Fiselier return *this; 585a9e65961SEric Fiselier } 586a9e65961SEric Fiselier 587a9e65961SEric Fiselier _LIBCPP_INLINE_VISIBILITY 588f2d571c8SCasey Carter __optional_copy_assign_base& operator=(__optional_copy_assign_base&&) = default; 589f2d571c8SCasey Carter}; 590f2d571c8SCasey Carter 591f2d571c8SCasey Cartertemplate <class _Tp, bool = 592f2d571c8SCasey Carter is_trivially_destructible<_Tp>::value && 593f2d571c8SCasey Carter is_trivially_move_constructible<_Tp>::value && 594f2d571c8SCasey Carter is_trivially_move_assignable<_Tp>::value> 595f2d571c8SCasey Carterstruct __optional_move_assign_base : __optional_copy_assign_base<_Tp> 596f2d571c8SCasey Carter{ 597f2d571c8SCasey Carter using __optional_copy_assign_base<_Tp>::__optional_copy_assign_base; 598f2d571c8SCasey Carter}; 599f2d571c8SCasey Carter 600f2d571c8SCasey Cartertemplate <class _Tp> 601f2d571c8SCasey Carterstruct __optional_move_assign_base<_Tp, false> : __optional_copy_assign_base<_Tp> 602f2d571c8SCasey Carter{ 603f2d571c8SCasey Carter using value_type = _Tp; 604f2d571c8SCasey Carter using __optional_copy_assign_base<_Tp>::__optional_copy_assign_base; 605f2d571c8SCasey Carter 606f2d571c8SCasey Carter _LIBCPP_INLINE_VISIBILITY 607f2d571c8SCasey Carter __optional_move_assign_base() = default; 608f2d571c8SCasey Carter _LIBCPP_INLINE_VISIBILITY 609f2d571c8SCasey Carter __optional_move_assign_base(const __optional_move_assign_base& __opt) = default; 610f2d571c8SCasey Carter _LIBCPP_INLINE_VISIBILITY 611f2d571c8SCasey Carter __optional_move_assign_base(__optional_move_assign_base&&) = default; 612f2d571c8SCasey Carter _LIBCPP_INLINE_VISIBILITY 613f2d571c8SCasey Carter __optional_move_assign_base& operator=(const __optional_move_assign_base&) = default; 614f2d571c8SCasey Carter 615f2d571c8SCasey Carter _LIBCPP_INLINE_VISIBILITY 61654644993SChristopher Di Bella _LIBCPP_CONSTEXPR_AFTER_CXX17 __optional_move_assign_base& operator=(__optional_move_assign_base&& __opt) 617a9e65961SEric Fiselier noexcept(is_nothrow_move_assignable_v<value_type> && 618a9e65961SEric Fiselier is_nothrow_move_constructible_v<value_type>) 619a9e65961SEric Fiselier { 620a9e65961SEric Fiselier this->__assign_from(_VSTD::move(__opt)); 621a9e65961SEric Fiselier return *this; 622a9e65961SEric Fiselier } 623a9e65961SEric Fiselier}; 624a9e65961SEric Fiselier 625a9e65961SEric Fiseliertemplate <class _Tp> 626a9e65961SEric Fiselierusing __optional_sfinae_ctor_base_t = __sfinae_ctor_base< 627a9e65961SEric Fiselier is_copy_constructible<_Tp>::value, 628a9e65961SEric Fiselier is_move_constructible<_Tp>::value 629a9e65961SEric Fiselier>; 630a9e65961SEric Fiselier 631a9e65961SEric Fiseliertemplate <class _Tp> 632a9e65961SEric Fiselierusing __optional_sfinae_assign_base_t = __sfinae_assign_base< 633a9e65961SEric Fiselier (is_copy_constructible<_Tp>::value && is_copy_assignable<_Tp>::value), 634a9e65961SEric Fiselier (is_move_constructible<_Tp>::value && is_move_assignable<_Tp>::value) 635a9e65961SEric Fiselier>; 636a9e65961SEric Fiselier 637a9e65961SEric Fiseliertemplate<class _Tp> 63817cfc57dSNikolas Klauserclass optional; 63917cfc57dSNikolas Klausertemplate <class _Tp> 64017cfc57dSNikolas Klauserstruct __is_std_optional : false_type {}; 64117cfc57dSNikolas Klausertemplate <class _Tp> struct __is_std_optional<optional<_Tp>> : true_type {}; 64217cfc57dSNikolas Klauser 64317cfc57dSNikolas Klausertemplate <class _Tp> 644a9e65961SEric Fiselierclass optional 645f2d571c8SCasey Carter : private __optional_move_assign_base<_Tp> 646a9e65961SEric Fiselier , private __optional_sfinae_ctor_base_t<_Tp> 647a9e65961SEric Fiselier , private __optional_sfinae_assign_base_t<_Tp> 648a9e65961SEric Fiselier{ 649f2d571c8SCasey Carter using __base = __optional_move_assign_base<_Tp>; 650a9e65961SEric Fiselierpublic: 651a9e65961SEric Fiselier using value_type = _Tp; 652a9e65961SEric Fiselier 653a9e65961SEric Fiselierprivate: 654a9e65961SEric Fiselier // Disable the reference extension using this static assert. 65536db4898SMarshall Clow static_assert(!is_same_v<__uncvref_t<value_type>, in_place_t>, 656a9e65961SEric Fiselier "instantiation of optional with in_place_t is ill-formed"); 657a9e65961SEric Fiselier static_assert(!is_same_v<__uncvref_t<value_type>, nullopt_t>, 658a9e65961SEric Fiselier "instantiation of optional with nullopt_t is ill-formed"); 659a9e65961SEric Fiselier static_assert(!is_reference_v<value_type>, 660a9e65961SEric Fiselier "instantiation of optional with a reference type is ill-formed"); 661a9e65961SEric Fiselier static_assert(is_destructible_v<value_type>, 662a9e65961SEric Fiselier "instantiation of optional with a non-destructible type is ill-formed"); 66336db4898SMarshall Clow static_assert(!is_array_v<value_type>, 66436db4898SMarshall Clow "instantiation of optional with an array type is ill-formed"); 665a9e65961SEric Fiselier 666a9e65961SEric Fiselier // LWG2756: conditionally explicit conversion from _Up 667a9e65961SEric Fiselier struct _CheckOptionalArgsConstructor { 668a9e65961SEric Fiselier template <class _Up> 669a9e65961SEric Fiselier static constexpr bool __enable_implicit() { 670a9e65961SEric Fiselier return is_constructible_v<_Tp, _Up&&> && 671a9e65961SEric Fiselier is_convertible_v<_Up&&, _Tp>; 672a9e65961SEric Fiselier } 673a9e65961SEric Fiselier 674a9e65961SEric Fiselier template <class _Up> 675a9e65961SEric Fiselier static constexpr bool __enable_explicit() { 676a9e65961SEric Fiselier return is_constructible_v<_Tp, _Up&&> && 677a9e65961SEric Fiselier !is_convertible_v<_Up&&, _Tp>; 678a9e65961SEric Fiselier } 679a9e65961SEric Fiselier }; 680a9e65961SEric Fiselier template <class _Up> 6813359a17bSEric Fiselier using _CheckOptionalArgsCtor = _If< 6823359a17bSEric Fiselier _IsNotSame<__uncvref_t<_Up>, in_place_t>::value && 6833359a17bSEric Fiselier _IsNotSame<__uncvref_t<_Up>, optional>::value, 684a9e65961SEric Fiselier _CheckOptionalArgsConstructor, 685a9e65961SEric Fiselier __check_tuple_constructor_fail 686a9e65961SEric Fiselier >; 687a9e65961SEric Fiselier template <class _QualUp> 688a9e65961SEric Fiselier struct _CheckOptionalLikeConstructor { 689a9e65961SEric Fiselier template <class _Up, class _Opt = optional<_Up>> 6903359a17bSEric Fiselier using __check_constructible_from_opt = _Or< 691a9e65961SEric Fiselier is_constructible<_Tp, _Opt&>, 692a9e65961SEric Fiselier is_constructible<_Tp, _Opt const&>, 693a9e65961SEric Fiselier is_constructible<_Tp, _Opt&&>, 694a9e65961SEric Fiselier is_constructible<_Tp, _Opt const&&>, 695a9e65961SEric Fiselier is_convertible<_Opt&, _Tp>, 696a9e65961SEric Fiselier is_convertible<_Opt const&, _Tp>, 697a9e65961SEric Fiselier is_convertible<_Opt&&, _Tp>, 698a9e65961SEric Fiselier is_convertible<_Opt const&&, _Tp> 699a9e65961SEric Fiselier >; 700a9e65961SEric Fiselier template <class _Up, class _Opt = optional<_Up>> 7013359a17bSEric Fiselier using __check_assignable_from_opt = _Or< 702a9e65961SEric Fiselier is_assignable<_Tp&, _Opt&>, 703a9e65961SEric Fiselier is_assignable<_Tp&, _Opt const&>, 704a9e65961SEric Fiselier is_assignable<_Tp&, _Opt&&>, 705a9e65961SEric Fiselier is_assignable<_Tp&, _Opt const&&> 706a9e65961SEric Fiselier >; 707a9e65961SEric Fiselier template <class _Up, class _QUp = _QualUp> 708a9e65961SEric Fiselier static constexpr bool __enable_implicit() { 709a9e65961SEric Fiselier return is_convertible<_QUp, _Tp>::value && 710a9e65961SEric Fiselier !__check_constructible_from_opt<_Up>::value; 711a9e65961SEric Fiselier } 712a9e65961SEric Fiselier template <class _Up, class _QUp = _QualUp> 713a9e65961SEric Fiselier static constexpr bool __enable_explicit() { 714a9e65961SEric Fiselier return !is_convertible<_QUp, _Tp>::value && 715a9e65961SEric Fiselier !__check_constructible_from_opt<_Up>::value; 716a9e65961SEric Fiselier } 717a9e65961SEric Fiselier template <class _Up, class _QUp = _QualUp> 718a9e65961SEric Fiselier static constexpr bool __enable_assign() { 719b6f19174SArthur O'Dwyer // Construction and assignability of _QUp to _Tp has already been 720a9e65961SEric Fiselier // checked. 721a9e65961SEric Fiselier return !__check_constructible_from_opt<_Up>::value && 722a9e65961SEric Fiselier !__check_assignable_from_opt<_Up>::value; 723a9e65961SEric Fiselier } 724a9e65961SEric Fiselier }; 725a9e65961SEric Fiselier 726a9e65961SEric Fiselier template <class _Up, class _QualUp> 7273359a17bSEric Fiselier using _CheckOptionalLikeCtor = _If< 7283359a17bSEric Fiselier _And< 7293359a17bSEric Fiselier _IsNotSame<_Up, _Tp>, 730a9e65961SEric Fiselier is_constructible<_Tp, _QualUp> 731a9e65961SEric Fiselier >::value, 732a9e65961SEric Fiselier _CheckOptionalLikeConstructor<_QualUp>, 733a9e65961SEric Fiselier __check_tuple_constructor_fail 734a9e65961SEric Fiselier >; 735a9e65961SEric Fiselier template <class _Up, class _QualUp> 7363359a17bSEric Fiselier using _CheckOptionalLikeAssign = _If< 7373359a17bSEric Fiselier _And< 7383359a17bSEric Fiselier _IsNotSame<_Up, _Tp>, 739a9e65961SEric Fiselier is_constructible<_Tp, _QualUp>, 740a9e65961SEric Fiselier is_assignable<_Tp&, _QualUp> 741a9e65961SEric Fiselier >::value, 742a9e65961SEric Fiselier _CheckOptionalLikeConstructor<_QualUp>, 743a9e65961SEric Fiselier __check_tuple_constructor_fail 744a9e65961SEric Fiselier >; 74517cfc57dSNikolas Klauser 746a9e65961SEric Fiselierpublic: 747a9e65961SEric Fiselier 748a9e65961SEric Fiselier _LIBCPP_INLINE_VISIBILITY constexpr optional() noexcept {} 749c1bcd4c1SMarshall Clow _LIBCPP_INLINE_VISIBILITY constexpr optional(const optional&) = default; 750c1bcd4c1SMarshall Clow _LIBCPP_INLINE_VISIBILITY constexpr optional(optional&&) = default; 751a9e65961SEric Fiselier _LIBCPP_INLINE_VISIBILITY constexpr optional(nullopt_t) noexcept {} 752a9e65961SEric Fiselier 7534e0ea2cfSLouis Dionne template <class _InPlaceT, class... _Args, class = enable_if_t< 7543359a17bSEric Fiselier _And< 7553359a17bSEric Fiselier _IsSame<_InPlaceT, in_place_t>, 75686af6f50SEric Fiselier is_constructible<value_type, _Args...> 75786af6f50SEric Fiselier >::value 75886af6f50SEric Fiselier > 759a9e65961SEric Fiselier > 760a9e65961SEric Fiselier _LIBCPP_INLINE_VISIBILITY 76186af6f50SEric Fiselier constexpr explicit optional(_InPlaceT, _Args&&... __args) 762a9e65961SEric Fiselier : __base(in_place, _VSTD::forward<_Args>(__args)...) {} 763a9e65961SEric Fiselier 7644e0ea2cfSLouis Dionne template <class _Up, class... _Args, class = enable_if_t< 765a9e65961SEric Fiselier is_constructible_v<value_type, initializer_list<_Up>&, _Args...>> 766a9e65961SEric Fiselier > 767a9e65961SEric Fiselier _LIBCPP_INLINE_VISIBILITY 768a9e65961SEric Fiselier constexpr explicit optional(in_place_t, initializer_list<_Up> __il, _Args&&... __args) 769a9e65961SEric Fiselier : __base(in_place, __il, _VSTD::forward<_Args>(__args)...) {} 770a9e65961SEric Fiselier 7714e0ea2cfSLouis Dionne template <class _Up = value_type, enable_if_t< 772a9e65961SEric Fiselier _CheckOptionalArgsCtor<_Up>::template __enable_implicit<_Up>() 773a9e65961SEric Fiselier , int> = 0> 774a9e65961SEric Fiselier _LIBCPP_INLINE_VISIBILITY 775a9e65961SEric Fiselier constexpr optional(_Up&& __v) 776a9e65961SEric Fiselier : __base(in_place, _VSTD::forward<_Up>(__v)) {} 777a9e65961SEric Fiselier 7784e0ea2cfSLouis Dionne template <class _Up, enable_if_t< 779a9e65961SEric Fiselier _CheckOptionalArgsCtor<_Up>::template __enable_explicit<_Up>() 780a9e65961SEric Fiselier , int> = 0> 781a9e65961SEric Fiselier _LIBCPP_INLINE_VISIBILITY 782a9e65961SEric Fiselier constexpr explicit optional(_Up&& __v) 783a9e65961SEric Fiselier : __base(in_place, _VSTD::forward<_Up>(__v)) {} 784a9e65961SEric Fiselier 785a9e65961SEric Fiselier // LWG2756: conditionally explicit conversion from const optional<_Up>& 7864e0ea2cfSLouis Dionne template <class _Up, enable_if_t< 787a9e65961SEric Fiselier _CheckOptionalLikeCtor<_Up, _Up const&>::template __enable_implicit<_Up>() 788a9e65961SEric Fiselier , int> = 0> 789a9e65961SEric Fiselier _LIBCPP_INLINE_VISIBILITY 79054644993SChristopher Di Bella _LIBCPP_CONSTEXPR_AFTER_CXX17 optional(const optional<_Up>& __v) 791a9e65961SEric Fiselier { 792a9e65961SEric Fiselier this->__construct_from(__v); 793a9e65961SEric Fiselier } 7944e0ea2cfSLouis Dionne template <class _Up, enable_if_t< 795a9e65961SEric Fiselier _CheckOptionalLikeCtor<_Up, _Up const&>::template __enable_explicit<_Up>() 796a9e65961SEric Fiselier , int> = 0> 797a9e65961SEric Fiselier _LIBCPP_INLINE_VISIBILITY 79854644993SChristopher Di Bella _LIBCPP_CONSTEXPR_AFTER_CXX17 explicit optional(const optional<_Up>& __v) 799a9e65961SEric Fiselier { 800a9e65961SEric Fiselier this->__construct_from(__v); 801a9e65961SEric Fiselier } 802a9e65961SEric Fiselier 803a9e65961SEric Fiselier // LWG2756: conditionally explicit conversion from optional<_Up>&& 8044e0ea2cfSLouis Dionne template <class _Up, enable_if_t< 805a9e65961SEric Fiselier _CheckOptionalLikeCtor<_Up, _Up &&>::template __enable_implicit<_Up>() 806a9e65961SEric Fiselier , int> = 0> 807a9e65961SEric Fiselier _LIBCPP_INLINE_VISIBILITY 80854644993SChristopher Di Bella _LIBCPP_CONSTEXPR_AFTER_CXX17 optional(optional<_Up>&& __v) 809a9e65961SEric Fiselier { 810a9e65961SEric Fiselier this->__construct_from(_VSTD::move(__v)); 811a9e65961SEric Fiselier } 8124e0ea2cfSLouis Dionne template <class _Up, enable_if_t< 813a9e65961SEric Fiselier _CheckOptionalLikeCtor<_Up, _Up &&>::template __enable_explicit<_Up>() 814a9e65961SEric Fiselier , int> = 0> 815a9e65961SEric Fiselier _LIBCPP_INLINE_VISIBILITY 81654644993SChristopher Di Bella _LIBCPP_CONSTEXPR_AFTER_CXX17 explicit optional(optional<_Up>&& __v) 817a9e65961SEric Fiselier { 818a9e65961SEric Fiselier this->__construct_from(_VSTD::move(__v)); 819a9e65961SEric Fiselier } 820a9e65961SEric Fiselier 82117cfc57dSNikolas Klauser#if _LIBCPP_STD_VER > 20 82217cfc57dSNikolas Klauser template<class _Fp, class... _Args> 82317cfc57dSNikolas Klauser _LIBCPP_HIDE_FROM_ABI 82417cfc57dSNikolas Klauser constexpr explicit optional(__optional_construct_from_invoke_tag, _Fp&& __f, _Args&&... __args) 82517cfc57dSNikolas Klauser : __base(__optional_construct_from_invoke_tag{}, _VSTD::forward<_Fp>(__f), _VSTD::forward<_Args>(__args)...) { 82617cfc57dSNikolas Klauser } 82717cfc57dSNikolas Klauser#endif 82817cfc57dSNikolas Klauser 829a9e65961SEric Fiselier _LIBCPP_INLINE_VISIBILITY 83054644993SChristopher Di Bella _LIBCPP_CONSTEXPR_AFTER_CXX17 optional& operator=(nullopt_t) noexcept 831a9e65961SEric Fiselier { 832a9e65961SEric Fiselier reset(); 833a9e65961SEric Fiselier return *this; 834a9e65961SEric Fiselier } 835a9e65961SEric Fiselier 836a9e65961SEric Fiselier _LIBCPP_INLINE_VISIBILITY optional& operator=(const optional&) = default; 837a9e65961SEric Fiselier _LIBCPP_INLINE_VISIBILITY optional& operator=(optional&&) = default; 838a9e65961SEric Fiselier 839a9e65961SEric Fiselier // LWG2756 840a9e65961SEric Fiselier template <class _Up = value_type, 8414e0ea2cfSLouis Dionne class = enable_if_t< 8423359a17bSEric Fiselier _And< 8433359a17bSEric Fiselier _IsNotSame<__uncvref_t<_Up>, optional>, 8443359a17bSEric Fiselier _Or< 845954014a0SMarshall Clow _IsNotSame<__uncvref_t<_Up>, value_type>, 8463359a17bSEric Fiselier _Not<is_scalar<value_type>> 847015fcffdSEric Fiselier >, 848015fcffdSEric Fiselier is_constructible<value_type, _Up>, 849015fcffdSEric Fiselier is_assignable<value_type&, _Up> 850015fcffdSEric Fiselier >::value> 851a9e65961SEric Fiselier > 852a9e65961SEric Fiselier _LIBCPP_INLINE_VISIBILITY 85354644993SChristopher Di Bella _LIBCPP_CONSTEXPR_AFTER_CXX17 optional& 854a9e65961SEric Fiselier operator=(_Up&& __v) 855a9e65961SEric Fiselier { 856a9e65961SEric Fiselier if (this->has_value()) 857a9e65961SEric Fiselier this->__get() = _VSTD::forward<_Up>(__v); 858a9e65961SEric Fiselier else 859a9e65961SEric Fiselier this->__construct(_VSTD::forward<_Up>(__v)); 860a9e65961SEric Fiselier return *this; 861a9e65961SEric Fiselier } 862a9e65961SEric Fiselier 863a9e65961SEric Fiselier // LWG2756 8644e0ea2cfSLouis Dionne template <class _Up, enable_if_t< 865a9e65961SEric Fiselier _CheckOptionalLikeAssign<_Up, _Up const&>::template __enable_assign<_Up>() 866a9e65961SEric Fiselier , int> = 0> 867a9e65961SEric Fiselier _LIBCPP_INLINE_VISIBILITY 86854644993SChristopher Di Bella _LIBCPP_CONSTEXPR_AFTER_CXX17 optional& 869a9e65961SEric Fiselier operator=(const optional<_Up>& __v) 870a9e65961SEric Fiselier { 871a9e65961SEric Fiselier this->__assign_from(__v); 872a9e65961SEric Fiselier return *this; 873a9e65961SEric Fiselier } 874a9e65961SEric Fiselier 875a9e65961SEric Fiselier // LWG2756 8764e0ea2cfSLouis Dionne template <class _Up, enable_if_t< 877a9e65961SEric Fiselier _CheckOptionalLikeCtor<_Up, _Up &&>::template __enable_assign<_Up>() 878a9e65961SEric Fiselier , int> = 0> 879a9e65961SEric Fiselier _LIBCPP_INLINE_VISIBILITY 88054644993SChristopher Di Bella _LIBCPP_CONSTEXPR_AFTER_CXX17 optional& 881a9e65961SEric Fiselier operator=(optional<_Up>&& __v) 882a9e65961SEric Fiselier { 883a9e65961SEric Fiselier this->__assign_from(_VSTD::move(__v)); 884a9e65961SEric Fiselier return *this; 885a9e65961SEric Fiselier } 886a9e65961SEric Fiselier 887a9e65961SEric Fiselier template <class... _Args, 8884e0ea2cfSLouis Dionne class = enable_if_t 889a9e65961SEric Fiselier < 890a9e65961SEric Fiselier is_constructible_v<value_type, _Args...> 891a9e65961SEric Fiselier > 892a9e65961SEric Fiselier > 893a9e65961SEric Fiselier _LIBCPP_INLINE_VISIBILITY 89454644993SChristopher Di Bella _LIBCPP_CONSTEXPR_AFTER_CXX17 _Tp & 895a9e65961SEric Fiselier emplace(_Args&&... __args) 896a9e65961SEric Fiselier { 897a9e65961SEric Fiselier reset(); 898a9e65961SEric Fiselier this->__construct(_VSTD::forward<_Args>(__args)...); 8995c80f4f6SMarshall Clow return this->__get(); 900a9e65961SEric Fiselier } 901a9e65961SEric Fiselier 902a9e65961SEric Fiselier template <class _Up, class... _Args, 9034e0ea2cfSLouis Dionne class = enable_if_t 904a9e65961SEric Fiselier < 905a9e65961SEric Fiselier is_constructible_v<value_type, initializer_list<_Up>&, _Args...> 906a9e65961SEric Fiselier > 907a9e65961SEric Fiselier > 908a9e65961SEric Fiselier _LIBCPP_INLINE_VISIBILITY 90954644993SChristopher Di Bella _LIBCPP_CONSTEXPR_AFTER_CXX17 _Tp & 910a9e65961SEric Fiselier emplace(initializer_list<_Up> __il, _Args&&... __args) 911a9e65961SEric Fiselier { 912a9e65961SEric Fiselier reset(); 913a9e65961SEric Fiselier this->__construct(__il, _VSTD::forward<_Args>(__args)...); 9145c80f4f6SMarshall Clow return this->__get(); 915a9e65961SEric Fiselier } 916a9e65961SEric Fiselier 917a9e65961SEric Fiselier _LIBCPP_INLINE_VISIBILITY 91854644993SChristopher Di Bella _LIBCPP_CONSTEXPR_AFTER_CXX17 void swap(optional& __opt) 919a9e65961SEric Fiselier noexcept(is_nothrow_move_constructible_v<value_type> && 920a9e65961SEric Fiselier is_nothrow_swappable_v<value_type>) 921a9e65961SEric Fiselier { 922a9e65961SEric Fiselier if (this->has_value() == __opt.has_value()) 923a9e65961SEric Fiselier { 924a9e65961SEric Fiselier using _VSTD::swap; 925a9e65961SEric Fiselier if (this->has_value()) 926a9e65961SEric Fiselier swap(this->__get(), __opt.__get()); 927a9e65961SEric Fiselier } 928a9e65961SEric Fiselier else 929a9e65961SEric Fiselier { 930a9e65961SEric Fiselier if (this->has_value()) 931a9e65961SEric Fiselier { 932a9e65961SEric Fiselier __opt.__construct(_VSTD::move(this->__get())); 933a9e65961SEric Fiselier reset(); 934a9e65961SEric Fiselier } 935a9e65961SEric Fiselier else 936a9e65961SEric Fiselier { 937a9e65961SEric Fiselier this->__construct(_VSTD::move(__opt.__get())); 938a9e65961SEric Fiselier __opt.reset(); 939a9e65961SEric Fiselier } 940a9e65961SEric Fiselier } 941a9e65961SEric Fiselier } 942a9e65961SEric Fiselier 943a9e65961SEric Fiselier _LIBCPP_INLINE_VISIBILITY 944a9e65961SEric Fiselier constexpr 945a9e65961SEric Fiselier add_pointer_t<value_type const> 946a9e65961SEric Fiselier operator->() const 947a9e65961SEric Fiselier { 94896100f15SKristina Bessonova _LIBCPP_ASSERT(this->has_value(), "optional operator-> called on a disengaged value"); 949a9e65961SEric Fiselier return _VSTD::addressof(this->__get()); 950a9e65961SEric Fiselier } 951a9e65961SEric Fiselier 952a9e65961SEric Fiselier _LIBCPP_INLINE_VISIBILITY 953a9e65961SEric Fiselier constexpr 954a9e65961SEric Fiselier add_pointer_t<value_type> 955a9e65961SEric Fiselier operator->() 956a9e65961SEric Fiselier { 95796100f15SKristina Bessonova _LIBCPP_ASSERT(this->has_value(), "optional operator-> called on a disengaged value"); 958a9e65961SEric Fiselier return _VSTD::addressof(this->__get()); 959a9e65961SEric Fiselier } 960a9e65961SEric Fiselier 961a9e65961SEric Fiselier _LIBCPP_INLINE_VISIBILITY 962a9e65961SEric Fiselier constexpr 963a9e65961SEric Fiselier const value_type& 96400044421Szoecarver operator*() const& noexcept 965a9e65961SEric Fiselier { 96696100f15SKristina Bessonova _LIBCPP_ASSERT(this->has_value(), "optional operator* called on a disengaged value"); 967a9e65961SEric Fiselier return this->__get(); 968a9e65961SEric Fiselier } 969a9e65961SEric Fiselier 970a9e65961SEric Fiselier _LIBCPP_INLINE_VISIBILITY 971a9e65961SEric Fiselier constexpr 972a9e65961SEric Fiselier value_type& 97300044421Szoecarver operator*() & noexcept 974a9e65961SEric Fiselier { 97596100f15SKristina Bessonova _LIBCPP_ASSERT(this->has_value(), "optional operator* called on a disengaged value"); 976a9e65961SEric Fiselier return this->__get(); 977a9e65961SEric Fiselier } 978a9e65961SEric Fiselier 979a9e65961SEric Fiselier _LIBCPP_INLINE_VISIBILITY 980a9e65961SEric Fiselier constexpr 981a9e65961SEric Fiselier value_type&& 98200044421Szoecarver operator*() && noexcept 983a9e65961SEric Fiselier { 98496100f15SKristina Bessonova _LIBCPP_ASSERT(this->has_value(), "optional operator* called on a disengaged value"); 985a9e65961SEric Fiselier return _VSTD::move(this->__get()); 986a9e65961SEric Fiselier } 987a9e65961SEric Fiselier 988a9e65961SEric Fiselier _LIBCPP_INLINE_VISIBILITY 989a9e65961SEric Fiselier constexpr 990a9e65961SEric Fiselier const value_type&& 99100044421Szoecarver operator*() const&& noexcept 992a9e65961SEric Fiselier { 99396100f15SKristina Bessonova _LIBCPP_ASSERT(this->has_value(), "optional operator* called on a disengaged value"); 994a9e65961SEric Fiselier return _VSTD::move(this->__get()); 995a9e65961SEric Fiselier } 996a9e65961SEric Fiselier 997a9e65961SEric Fiselier _LIBCPP_INLINE_VISIBILITY 998a9e65961SEric Fiselier constexpr explicit operator bool() const noexcept { return has_value(); } 999a9e65961SEric Fiselier 1000a9e65961SEric Fiselier using __base::has_value; 1001a9e65961SEric Fiselier using __base::__get; 1002a9e65961SEric Fiselier 1003a9e65961SEric Fiselier _LIBCPP_INLINE_VISIBILITY 10048a063df1SLouis Dionne _LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS 1005a9e65961SEric Fiselier constexpr value_type const& value() const& 1006a9e65961SEric Fiselier { 1007a9e65961SEric Fiselier if (!this->has_value()) 1008a9e65961SEric Fiselier __throw_bad_optional_access(); 1009a9e65961SEric Fiselier return this->__get(); 1010a9e65961SEric Fiselier } 1011a9e65961SEric Fiselier 1012a9e65961SEric Fiselier _LIBCPP_INLINE_VISIBILITY 10138a063df1SLouis Dionne _LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS 1014a9e65961SEric Fiselier constexpr value_type& value() & 1015a9e65961SEric Fiselier { 1016a9e65961SEric Fiselier if (!this->has_value()) 1017a9e65961SEric Fiselier __throw_bad_optional_access(); 1018a9e65961SEric Fiselier return this->__get(); 1019a9e65961SEric Fiselier } 1020a9e65961SEric Fiselier 1021a9e65961SEric Fiselier _LIBCPP_INLINE_VISIBILITY 10228a063df1SLouis Dionne _LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS 1023a9e65961SEric Fiselier constexpr value_type&& value() && 1024a9e65961SEric Fiselier { 1025a9e65961SEric Fiselier if (!this->has_value()) 1026a9e65961SEric Fiselier __throw_bad_optional_access(); 1027a9e65961SEric Fiselier return _VSTD::move(this->__get()); 1028a9e65961SEric Fiselier } 1029a9e65961SEric Fiselier 1030a9e65961SEric Fiselier _LIBCPP_INLINE_VISIBILITY 10318a063df1SLouis Dionne _LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS 1032a9e65961SEric Fiselier constexpr value_type const&& value() const&& 1033a9e65961SEric Fiselier { 1034a9e65961SEric Fiselier if (!this->has_value()) 1035a9e65961SEric Fiselier __throw_bad_optional_access(); 1036a9e65961SEric Fiselier return _VSTD::move(this->__get()); 1037a9e65961SEric Fiselier } 1038a9e65961SEric Fiselier 1039a9e65961SEric Fiselier template <class _Up> 1040a9e65961SEric Fiselier _LIBCPP_INLINE_VISIBILITY 1041a9e65961SEric Fiselier constexpr value_type value_or(_Up&& __v) const& 1042a9e65961SEric Fiselier { 1043a9e65961SEric Fiselier static_assert(is_copy_constructible_v<value_type>, 1044a9e65961SEric Fiselier "optional<T>::value_or: T must be copy constructible"); 1045a9e65961SEric Fiselier static_assert(is_convertible_v<_Up, value_type>, 1046a9e65961SEric Fiselier "optional<T>::value_or: U must be convertible to T"); 1047a9e65961SEric Fiselier return this->has_value() ? this->__get() : 1048a9e65961SEric Fiselier static_cast<value_type>(_VSTD::forward<_Up>(__v)); 1049a9e65961SEric Fiselier } 1050a9e65961SEric Fiselier 1051a9e65961SEric Fiselier template <class _Up> 1052a9e65961SEric Fiselier _LIBCPP_INLINE_VISIBILITY 1053dd7c68bcSCasey Carter constexpr value_type value_or(_Up&& __v) && 1054a9e65961SEric Fiselier { 1055a9e65961SEric Fiselier static_assert(is_move_constructible_v<value_type>, 1056a9e65961SEric Fiselier "optional<T>::value_or: T must be move constructible"); 1057a9e65961SEric Fiselier static_assert(is_convertible_v<_Up, value_type>, 1058a9e65961SEric Fiselier "optional<T>::value_or: U must be convertible to T"); 1059a9e65961SEric Fiselier return this->has_value() ? _VSTD::move(this->__get()) : 1060a9e65961SEric Fiselier static_cast<value_type>(_VSTD::forward<_Up>(__v)); 1061a9e65961SEric Fiselier } 1062a9e65961SEric Fiselier 106317cfc57dSNikolas Klauser#if _LIBCPP_STD_VER > 20 106417cfc57dSNikolas Klauser template<class _Func> 1065fd4cc870SLouis Dionne _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS 106617cfc57dSNikolas Klauser constexpr auto and_then(_Func&& __f) & { 106717cfc57dSNikolas Klauser using _Up = invoke_result_t<_Func, value_type&>; 106817cfc57dSNikolas Klauser static_assert(__is_std_optional<remove_cvref_t<_Up>>::value, 106917cfc57dSNikolas Klauser "Result of f(value()) must be a specialization of std::optional"); 107017cfc57dSNikolas Klauser if (*this) 107117cfc57dSNikolas Klauser return _VSTD::invoke(_VSTD::forward<_Func>(__f), value()); 107217cfc57dSNikolas Klauser return remove_cvref_t<_Up>(); 107317cfc57dSNikolas Klauser } 107417cfc57dSNikolas Klauser 107517cfc57dSNikolas Klauser template<class _Func> 1076fd4cc870SLouis Dionne _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS 107717cfc57dSNikolas Klauser constexpr auto and_then(_Func&& __f) const& { 107817cfc57dSNikolas Klauser using _Up = invoke_result_t<_Func, const value_type&>; 107917cfc57dSNikolas Klauser static_assert(__is_std_optional<remove_cvref_t<_Up>>::value, 108017cfc57dSNikolas Klauser "Result of f(value()) must be a specialization of std::optional"); 108117cfc57dSNikolas Klauser if (*this) 108217cfc57dSNikolas Klauser return _VSTD::invoke(_VSTD::forward<_Func>(__f), value()); 108317cfc57dSNikolas Klauser return remove_cvref_t<_Up>(); 108417cfc57dSNikolas Klauser } 108517cfc57dSNikolas Klauser 108617cfc57dSNikolas Klauser template<class _Func> 1087fd4cc870SLouis Dionne _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS 108817cfc57dSNikolas Klauser constexpr auto and_then(_Func&& __f) && { 108917cfc57dSNikolas Klauser using _Up = invoke_result_t<_Func, value_type&&>; 109017cfc57dSNikolas Klauser static_assert(__is_std_optional<remove_cvref_t<_Up>>::value, 109117cfc57dSNikolas Klauser "Result of f(std::move(value())) must be a specialization of std::optional"); 109217cfc57dSNikolas Klauser if (*this) 109317cfc57dSNikolas Klauser return _VSTD::invoke(_VSTD::forward<_Func>(__f), _VSTD::move(value())); 109417cfc57dSNikolas Klauser return remove_cvref_t<_Up>(); 109517cfc57dSNikolas Klauser } 109617cfc57dSNikolas Klauser 109717cfc57dSNikolas Klauser template<class _Func> 109817cfc57dSNikolas Klauser _LIBCPP_HIDE_FROM_ABI 109917cfc57dSNikolas Klauser constexpr auto and_then(_Func&& __f) const&& { 110017cfc57dSNikolas Klauser using _Up = invoke_result_t<_Func, const value_type&&>; 110117cfc57dSNikolas Klauser static_assert(__is_std_optional<remove_cvref_t<_Up>>::value, 110217cfc57dSNikolas Klauser "Result of f(std::move(value())) must be a specialization of std::optional"); 110317cfc57dSNikolas Klauser if (*this) 110417cfc57dSNikolas Klauser return _VSTD::invoke(_VSTD::forward<_Func>(__f), _VSTD::move(value())); 110517cfc57dSNikolas Klauser return remove_cvref_t<_Up>(); 110617cfc57dSNikolas Klauser } 110717cfc57dSNikolas Klauser 110817cfc57dSNikolas Klauser template<class _Func> 1109fd4cc870SLouis Dionne _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS 111017cfc57dSNikolas Klauser constexpr auto transform(_Func&& __f) & { 111117cfc57dSNikolas Klauser using _Up = remove_cv_t<invoke_result_t<_Func, value_type&>>; 111217cfc57dSNikolas Klauser static_assert(!is_array_v<_Up>, "Result of f(value()) should not be an Array"); 111317cfc57dSNikolas Klauser static_assert(!is_same_v<_Up, in_place_t>, 111417cfc57dSNikolas Klauser "Result of f(value()) should not be std::in_place_t"); 111517cfc57dSNikolas Klauser static_assert(!is_same_v<_Up, nullopt_t>, 111617cfc57dSNikolas Klauser "Result of f(value()) should not be std::nullopt_t"); 111717cfc57dSNikolas Klauser static_assert(is_object_v<_Up>, "Result of f(value()) should be an object type"); 111817cfc57dSNikolas Klauser if (*this) 111917cfc57dSNikolas Klauser return optional<_Up>(__optional_construct_from_invoke_tag{}, _VSTD::forward<_Func>(__f), value()); 112017cfc57dSNikolas Klauser return optional<_Up>(); 112117cfc57dSNikolas Klauser } 112217cfc57dSNikolas Klauser 112317cfc57dSNikolas Klauser template<class _Func> 1124fd4cc870SLouis Dionne _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS 112517cfc57dSNikolas Klauser constexpr auto transform(_Func&& __f) const& { 112617cfc57dSNikolas Klauser using _Up = remove_cv_t<invoke_result_t<_Func, const value_type&>>; 112717cfc57dSNikolas Klauser static_assert(!is_array_v<_Up>, "Result of f(value()) should not be an Array"); 112817cfc57dSNikolas Klauser static_assert(!is_same_v<_Up, in_place_t>, 112917cfc57dSNikolas Klauser "Result of f(value()) should not be std::in_place_t"); 113017cfc57dSNikolas Klauser static_assert(!is_same_v<_Up, nullopt_t>, 113117cfc57dSNikolas Klauser "Result of f(value()) should not be std::nullopt_t"); 113217cfc57dSNikolas Klauser static_assert(is_object_v<_Up>, "Result of f(value()) should be an object type"); 113317cfc57dSNikolas Klauser if (*this) 113417cfc57dSNikolas Klauser return optional<_Up>(__optional_construct_from_invoke_tag{}, _VSTD::forward<_Func>(__f), value()); 113517cfc57dSNikolas Klauser return optional<_Up>(); 113617cfc57dSNikolas Klauser } 113717cfc57dSNikolas Klauser 113817cfc57dSNikolas Klauser template<class _Func> 1139fd4cc870SLouis Dionne _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS 114017cfc57dSNikolas Klauser constexpr auto transform(_Func&& __f) && { 114117cfc57dSNikolas Klauser using _Up = remove_cv_t<invoke_result_t<_Func, value_type&&>>; 114217cfc57dSNikolas Klauser static_assert(!is_array_v<_Up>, "Result of f(std::move(value())) should not be an Array"); 114317cfc57dSNikolas Klauser static_assert(!is_same_v<_Up, in_place_t>, 114417cfc57dSNikolas Klauser "Result of f(std::move(value())) should not be std::in_place_t"); 114517cfc57dSNikolas Klauser static_assert(!is_same_v<_Up, nullopt_t>, 114617cfc57dSNikolas Klauser "Result of f(std::move(value())) should not be std::nullopt_t"); 114717cfc57dSNikolas Klauser static_assert(is_object_v<_Up>, "Result of f(std::move(value())) should be an object type"); 114817cfc57dSNikolas Klauser if (*this) 114917cfc57dSNikolas Klauser return optional<_Up>(__optional_construct_from_invoke_tag{}, _VSTD::forward<_Func>(__f), _VSTD::move(value())); 115017cfc57dSNikolas Klauser return optional<_Up>(); 115117cfc57dSNikolas Klauser } 115217cfc57dSNikolas Klauser 115317cfc57dSNikolas Klauser template<class _Func> 1154fd4cc870SLouis Dionne _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS 115517cfc57dSNikolas Klauser constexpr auto transform(_Func&& __f) const&& { 115617cfc57dSNikolas Klauser using _Up = remove_cvref_t<invoke_result_t<_Func, const value_type&&>>; 115717cfc57dSNikolas Klauser static_assert(!is_array_v<_Up>, "Result of f(std::move(value())) should not be an Array"); 115817cfc57dSNikolas Klauser static_assert(!is_same_v<_Up, in_place_t>, 115917cfc57dSNikolas Klauser "Result of f(std::move(value())) should not be std::in_place_t"); 116017cfc57dSNikolas Klauser static_assert(!is_same_v<_Up, nullopt_t>, 116117cfc57dSNikolas Klauser "Result of f(std::move(value())) should not be std::nullopt_t"); 116217cfc57dSNikolas Klauser static_assert(is_object_v<_Up>, "Result of f(std::move(value())) should be an object type"); 116317cfc57dSNikolas Klauser if (*this) 116417cfc57dSNikolas Klauser return optional<_Up>(__optional_construct_from_invoke_tag{}, _VSTD::forward<_Func>(__f), _VSTD::move(value())); 116517cfc57dSNikolas Klauser return optional<_Up>(); 116617cfc57dSNikolas Klauser } 116717cfc57dSNikolas Klauser 116817cfc57dSNikolas Klauser template<invocable _Func> 116917cfc57dSNikolas Klauser _LIBCPP_HIDE_FROM_ABI 117017cfc57dSNikolas Klauser constexpr optional or_else(_Func&& __f) const& requires is_copy_constructible_v<value_type> { 117117cfc57dSNikolas Klauser static_assert(is_same_v<remove_cvref_t<invoke_result_t<_Func>>, optional>, 117217cfc57dSNikolas Klauser "Result of f() should be the same type as this optional"); 117317cfc57dSNikolas Klauser if (*this) 117417cfc57dSNikolas Klauser return *this; 117517cfc57dSNikolas Klauser return _VSTD::forward<_Func>(__f)(); 117617cfc57dSNikolas Klauser } 117717cfc57dSNikolas Klauser 117817cfc57dSNikolas Klauser template<invocable _Func> 117917cfc57dSNikolas Klauser _LIBCPP_HIDE_FROM_ABI 118017cfc57dSNikolas Klauser constexpr optional or_else(_Func&& __f) && requires is_move_constructible_v<value_type> { 118117cfc57dSNikolas Klauser static_assert(is_same_v<remove_cvref_t<invoke_result_t<_Func>>, optional>, 118217cfc57dSNikolas Klauser "Result of f() should be the same type as this optional"); 118317cfc57dSNikolas Klauser if (*this) 118417cfc57dSNikolas Klauser return _VSTD::move(*this); 118517cfc57dSNikolas Klauser return _VSTD::forward<_Func>(__f)(); 118617cfc57dSNikolas Klauser } 118717cfc57dSNikolas Klauser#endif // _LIBCPP_STD_VER > 20 118817cfc57dSNikolas Klauser 1189a9e65961SEric Fiselier using __base::reset; 1190a9e65961SEric Fiselier}; 1191a9e65961SEric Fiselier 119201666904SLouis Dionne#if _LIBCPP_STD_VER >= 17 1193a8f1a715SArthur O'Dwyertemplate<class _Tp> 1194a8f1a715SArthur O'Dwyer optional(_Tp) -> optional<_Tp>; 1195f35b4bc3SMarshall Clow#endif 1196f35b4bc3SMarshall Clow 1197a9e65961SEric Fiselier// Comparisons between optionals 1198dc808af3SEric Fiseliertemplate <class _Tp, class _Up> 1199a9e65961SEric Fiselier_LIBCPP_INLINE_VISIBILITY constexpr 12004e0ea2cfSLouis Dionneenable_if_t< 1201ab3fcc50SArthur O'Dwyer is_convertible_v<decltype(declval<const _Tp&>() == 1202ab3fcc50SArthur O'Dwyer declval<const _Up&>()), bool>, 1203a9e65961SEric Fiselier bool 1204a9e65961SEric Fiselier> 1205dc808af3SEric Fiselieroperator==(const optional<_Tp>& __x, const optional<_Up>& __y) 1206a9e65961SEric Fiselier{ 1207a9e65961SEric Fiselier if (static_cast<bool>(__x) != static_cast<bool>(__y)) 1208a9e65961SEric Fiselier return false; 1209a9e65961SEric Fiselier if (!static_cast<bool>(__x)) 1210a9e65961SEric Fiselier return true; 1211a9e65961SEric Fiselier return *__x == *__y; 1212a9e65961SEric Fiselier} 1213a9e65961SEric Fiselier 1214dc808af3SEric Fiseliertemplate <class _Tp, class _Up> 1215a9e65961SEric Fiselier_LIBCPP_INLINE_VISIBILITY constexpr 12164e0ea2cfSLouis Dionneenable_if_t< 1217ab3fcc50SArthur O'Dwyer is_convertible_v<decltype(declval<const _Tp&>() != 1218ab3fcc50SArthur O'Dwyer declval<const _Up&>()), bool>, 1219a9e65961SEric Fiselier bool 1220a9e65961SEric Fiselier> 1221dc808af3SEric Fiselieroperator!=(const optional<_Tp>& __x, const optional<_Up>& __y) 1222a9e65961SEric Fiselier{ 1223a9e65961SEric Fiselier if (static_cast<bool>(__x) != static_cast<bool>(__y)) 1224a9e65961SEric Fiselier return true; 1225a9e65961SEric Fiselier if (!static_cast<bool>(__x)) 1226a9e65961SEric Fiselier return false; 1227a9e65961SEric Fiselier return *__x != *__y; 1228a9e65961SEric Fiselier} 1229a9e65961SEric Fiselier 1230dc808af3SEric Fiseliertemplate <class _Tp, class _Up> 1231a9e65961SEric Fiselier_LIBCPP_INLINE_VISIBILITY constexpr 12324e0ea2cfSLouis Dionneenable_if_t< 1233ab3fcc50SArthur O'Dwyer is_convertible_v<decltype(declval<const _Tp&>() < 1234ab3fcc50SArthur O'Dwyer declval<const _Up&>()), bool>, 1235a9e65961SEric Fiselier bool 1236a9e65961SEric Fiselier> 1237dc808af3SEric Fiselieroperator<(const optional<_Tp>& __x, const optional<_Up>& __y) 1238a9e65961SEric Fiselier{ 1239a9e65961SEric Fiselier if (!static_cast<bool>(__y)) 1240a9e65961SEric Fiselier return false; 1241a9e65961SEric Fiselier if (!static_cast<bool>(__x)) 1242a9e65961SEric Fiselier return true; 1243a9e65961SEric Fiselier return *__x < *__y; 1244a9e65961SEric Fiselier} 1245a9e65961SEric Fiselier 1246dc808af3SEric Fiseliertemplate <class _Tp, class _Up> 1247a9e65961SEric Fiselier_LIBCPP_INLINE_VISIBILITY constexpr 12484e0ea2cfSLouis Dionneenable_if_t< 1249ab3fcc50SArthur O'Dwyer is_convertible_v<decltype(declval<const _Tp&>() > 1250ab3fcc50SArthur O'Dwyer declval<const _Up&>()), bool>, 1251a9e65961SEric Fiselier bool 1252a9e65961SEric Fiselier> 1253dc808af3SEric Fiselieroperator>(const optional<_Tp>& __x, const optional<_Up>& __y) 1254a9e65961SEric Fiselier{ 1255a9e65961SEric Fiselier if (!static_cast<bool>(__x)) 1256a9e65961SEric Fiselier return false; 1257a9e65961SEric Fiselier if (!static_cast<bool>(__y)) 1258a9e65961SEric Fiselier return true; 1259a9e65961SEric Fiselier return *__x > *__y; 1260a9e65961SEric Fiselier} 1261a9e65961SEric Fiselier 1262dc808af3SEric Fiseliertemplate <class _Tp, class _Up> 1263a9e65961SEric Fiselier_LIBCPP_INLINE_VISIBILITY constexpr 12644e0ea2cfSLouis Dionneenable_if_t< 1265ab3fcc50SArthur O'Dwyer is_convertible_v<decltype(declval<const _Tp&>() <= 1266ab3fcc50SArthur O'Dwyer declval<const _Up&>()), bool>, 1267a9e65961SEric Fiselier bool 1268a9e65961SEric Fiselier> 1269dc808af3SEric Fiselieroperator<=(const optional<_Tp>& __x, const optional<_Up>& __y) 1270a9e65961SEric Fiselier{ 1271a9e65961SEric Fiselier if (!static_cast<bool>(__x)) 1272a9e65961SEric Fiselier return true; 1273a9e65961SEric Fiselier if (!static_cast<bool>(__y)) 1274a9e65961SEric Fiselier return false; 1275a9e65961SEric Fiselier return *__x <= *__y; 1276a9e65961SEric Fiselier} 1277a9e65961SEric Fiselier 1278dc808af3SEric Fiseliertemplate <class _Tp, class _Up> 1279a9e65961SEric Fiselier_LIBCPP_INLINE_VISIBILITY constexpr 12804e0ea2cfSLouis Dionneenable_if_t< 1281ab3fcc50SArthur O'Dwyer is_convertible_v<decltype(declval<const _Tp&>() >= 1282ab3fcc50SArthur O'Dwyer declval<const _Up&>()), bool>, 1283a9e65961SEric Fiselier bool 1284a9e65961SEric Fiselier> 1285dc808af3SEric Fiselieroperator>=(const optional<_Tp>& __x, const optional<_Up>& __y) 1286a9e65961SEric Fiselier{ 1287a9e65961SEric Fiselier if (!static_cast<bool>(__y)) 1288a9e65961SEric Fiselier return true; 1289a9e65961SEric Fiselier if (!static_cast<bool>(__x)) 1290a9e65961SEric Fiselier return false; 1291a9e65961SEric Fiselier return *__x >= *__y; 1292a9e65961SEric Fiselier} 1293a9e65961SEric Fiselier 1294a9e65961SEric Fiselier// Comparisons with nullopt 1295a9e65961SEric Fiseliertemplate <class _Tp> 1296a9e65961SEric Fiselier_LIBCPP_INLINE_VISIBILITY constexpr 1297a9e65961SEric Fiselierbool 1298a9e65961SEric Fiselieroperator==(const optional<_Tp>& __x, nullopt_t) noexcept 1299a9e65961SEric Fiselier{ 1300a9e65961SEric Fiselier return !static_cast<bool>(__x); 1301a9e65961SEric Fiselier} 1302a9e65961SEric Fiselier 1303a9e65961SEric Fiseliertemplate <class _Tp> 1304a9e65961SEric Fiselier_LIBCPP_INLINE_VISIBILITY constexpr 1305a9e65961SEric Fiselierbool 1306a9e65961SEric Fiselieroperator==(nullopt_t, const optional<_Tp>& __x) noexcept 1307a9e65961SEric Fiselier{ 1308a9e65961SEric Fiselier return !static_cast<bool>(__x); 1309a9e65961SEric Fiselier} 1310a9e65961SEric Fiselier 1311a9e65961SEric Fiseliertemplate <class _Tp> 1312a9e65961SEric Fiselier_LIBCPP_INLINE_VISIBILITY constexpr 1313a9e65961SEric Fiselierbool 1314a9e65961SEric Fiselieroperator!=(const optional<_Tp>& __x, nullopt_t) noexcept 1315a9e65961SEric Fiselier{ 1316a9e65961SEric Fiselier return static_cast<bool>(__x); 1317a9e65961SEric Fiselier} 1318a9e65961SEric Fiselier 1319a9e65961SEric Fiseliertemplate <class _Tp> 1320a9e65961SEric Fiselier_LIBCPP_INLINE_VISIBILITY constexpr 1321a9e65961SEric Fiselierbool 1322a9e65961SEric Fiselieroperator!=(nullopt_t, const optional<_Tp>& __x) noexcept 1323a9e65961SEric Fiselier{ 1324a9e65961SEric Fiselier return static_cast<bool>(__x); 1325a9e65961SEric Fiselier} 1326a9e65961SEric Fiselier 1327a9e65961SEric Fiseliertemplate <class _Tp> 1328a9e65961SEric Fiselier_LIBCPP_INLINE_VISIBILITY constexpr 1329a9e65961SEric Fiselierbool 1330a9e65961SEric Fiselieroperator<(const optional<_Tp>&, nullopt_t) noexcept 1331a9e65961SEric Fiselier{ 1332a9e65961SEric Fiselier return false; 1333a9e65961SEric Fiselier} 1334a9e65961SEric Fiselier 1335a9e65961SEric Fiseliertemplate <class _Tp> 1336a9e65961SEric Fiselier_LIBCPP_INLINE_VISIBILITY constexpr 1337a9e65961SEric Fiselierbool 1338a9e65961SEric Fiselieroperator<(nullopt_t, const optional<_Tp>& __x) noexcept 1339a9e65961SEric Fiselier{ 1340a9e65961SEric Fiselier return static_cast<bool>(__x); 1341a9e65961SEric Fiselier} 1342a9e65961SEric Fiselier 1343a9e65961SEric Fiseliertemplate <class _Tp> 1344a9e65961SEric Fiselier_LIBCPP_INLINE_VISIBILITY constexpr 1345a9e65961SEric Fiselierbool 1346a9e65961SEric Fiselieroperator<=(const optional<_Tp>& __x, nullopt_t) noexcept 1347a9e65961SEric Fiselier{ 1348a9e65961SEric Fiselier return !static_cast<bool>(__x); 1349a9e65961SEric Fiselier} 1350a9e65961SEric Fiselier 1351a9e65961SEric Fiseliertemplate <class _Tp> 1352a9e65961SEric Fiselier_LIBCPP_INLINE_VISIBILITY constexpr 1353a9e65961SEric Fiselierbool 1354fd838227SEric Fiselieroperator<=(nullopt_t, const optional<_Tp>&) noexcept 1355a9e65961SEric Fiselier{ 1356a9e65961SEric Fiselier return true; 1357a9e65961SEric Fiselier} 1358a9e65961SEric Fiselier 1359a9e65961SEric Fiseliertemplate <class _Tp> 1360a9e65961SEric Fiselier_LIBCPP_INLINE_VISIBILITY constexpr 1361a9e65961SEric Fiselierbool 1362a9e65961SEric Fiselieroperator>(const optional<_Tp>& __x, nullopt_t) noexcept 1363a9e65961SEric Fiselier{ 1364a9e65961SEric Fiselier return static_cast<bool>(__x); 1365a9e65961SEric Fiselier} 1366a9e65961SEric Fiselier 1367a9e65961SEric Fiseliertemplate <class _Tp> 1368a9e65961SEric Fiselier_LIBCPP_INLINE_VISIBILITY constexpr 1369a9e65961SEric Fiselierbool 1370fd838227SEric Fiselieroperator>(nullopt_t, const optional<_Tp>&) noexcept 1371a9e65961SEric Fiselier{ 1372a9e65961SEric Fiselier return false; 1373a9e65961SEric Fiselier} 1374a9e65961SEric Fiselier 1375a9e65961SEric Fiseliertemplate <class _Tp> 1376a9e65961SEric Fiselier_LIBCPP_INLINE_VISIBILITY constexpr 1377a9e65961SEric Fiselierbool 1378a9e65961SEric Fiselieroperator>=(const optional<_Tp>&, nullopt_t) noexcept 1379a9e65961SEric Fiselier{ 1380a9e65961SEric Fiselier return true; 1381a9e65961SEric Fiselier} 1382a9e65961SEric Fiselier 1383a9e65961SEric Fiseliertemplate <class _Tp> 1384a9e65961SEric Fiselier_LIBCPP_INLINE_VISIBILITY constexpr 1385a9e65961SEric Fiselierbool 1386a9e65961SEric Fiselieroperator>=(nullopt_t, const optional<_Tp>& __x) noexcept 1387a9e65961SEric Fiselier{ 1388a9e65961SEric Fiselier return !static_cast<bool>(__x); 1389a9e65961SEric Fiselier} 1390a9e65961SEric Fiselier 1391a9e65961SEric Fiselier// Comparisons with T 1392dc808af3SEric Fiseliertemplate <class _Tp, class _Up> 1393a9e65961SEric Fiselier_LIBCPP_INLINE_VISIBILITY constexpr 13944e0ea2cfSLouis Dionneenable_if_t< 1395ab3fcc50SArthur O'Dwyer is_convertible_v<decltype(declval<const _Tp&>() == 1396ab3fcc50SArthur O'Dwyer declval<const _Up&>()), bool>, 1397a9e65961SEric Fiselier bool 1398a9e65961SEric Fiselier> 1399dc808af3SEric Fiselieroperator==(const optional<_Tp>& __x, const _Up& __v) 1400a9e65961SEric Fiselier{ 1401a9e65961SEric Fiselier return static_cast<bool>(__x) ? *__x == __v : false; 1402a9e65961SEric Fiselier} 1403a9e65961SEric Fiselier 1404dc808af3SEric Fiseliertemplate <class _Tp, class _Up> 1405a9e65961SEric Fiselier_LIBCPP_INLINE_VISIBILITY constexpr 14064e0ea2cfSLouis Dionneenable_if_t< 1407ab3fcc50SArthur O'Dwyer is_convertible_v<decltype(declval<const _Tp&>() == 1408ab3fcc50SArthur O'Dwyer declval<const _Up&>()), bool>, 1409a9e65961SEric Fiselier bool 1410a9e65961SEric Fiselier> 1411dc808af3SEric Fiselieroperator==(const _Tp& __v, const optional<_Up>& __x) 1412a9e65961SEric Fiselier{ 1413a9e65961SEric Fiselier return static_cast<bool>(__x) ? __v == *__x : false; 1414a9e65961SEric Fiselier} 1415a9e65961SEric Fiselier 1416dc808af3SEric Fiseliertemplate <class _Tp, class _Up> 1417a9e65961SEric Fiselier_LIBCPP_INLINE_VISIBILITY constexpr 14184e0ea2cfSLouis Dionneenable_if_t< 1419ab3fcc50SArthur O'Dwyer is_convertible_v<decltype(declval<const _Tp&>() != 1420ab3fcc50SArthur O'Dwyer declval<const _Up&>()), bool>, 1421a9e65961SEric Fiselier bool 1422a9e65961SEric Fiselier> 1423dc808af3SEric Fiselieroperator!=(const optional<_Tp>& __x, const _Up& __v) 1424a9e65961SEric Fiselier{ 1425a9e65961SEric Fiselier return static_cast<bool>(__x) ? *__x != __v : true; 1426a9e65961SEric Fiselier} 1427a9e65961SEric Fiselier 1428dc808af3SEric Fiseliertemplate <class _Tp, class _Up> 1429a9e65961SEric Fiselier_LIBCPP_INLINE_VISIBILITY constexpr 14304e0ea2cfSLouis Dionneenable_if_t< 1431ab3fcc50SArthur O'Dwyer is_convertible_v<decltype(declval<const _Tp&>() != 1432ab3fcc50SArthur O'Dwyer declval<const _Up&>()), bool>, 1433a9e65961SEric Fiselier bool 1434a9e65961SEric Fiselier> 1435dc808af3SEric Fiselieroperator!=(const _Tp& __v, const optional<_Up>& __x) 1436a9e65961SEric Fiselier{ 1437a9e65961SEric Fiselier return static_cast<bool>(__x) ? __v != *__x : true; 1438a9e65961SEric Fiselier} 1439a9e65961SEric Fiselier 1440dc808af3SEric Fiseliertemplate <class _Tp, class _Up> 1441a9e65961SEric Fiselier_LIBCPP_INLINE_VISIBILITY constexpr 14424e0ea2cfSLouis Dionneenable_if_t< 1443ab3fcc50SArthur O'Dwyer is_convertible_v<decltype(declval<const _Tp&>() < 1444ab3fcc50SArthur O'Dwyer declval<const _Up&>()), bool>, 1445a9e65961SEric Fiselier bool 1446a9e65961SEric Fiselier> 1447dc808af3SEric Fiselieroperator<(const optional<_Tp>& __x, const _Up& __v) 1448a9e65961SEric Fiselier{ 1449a9e65961SEric Fiselier return static_cast<bool>(__x) ? *__x < __v : true; 1450a9e65961SEric Fiselier} 1451a9e65961SEric Fiselier 1452dc808af3SEric Fiseliertemplate <class _Tp, class _Up> 1453a9e65961SEric Fiselier_LIBCPP_INLINE_VISIBILITY constexpr 14544e0ea2cfSLouis Dionneenable_if_t< 1455ab3fcc50SArthur O'Dwyer is_convertible_v<decltype(declval<const _Tp&>() < 1456ab3fcc50SArthur O'Dwyer declval<const _Up&>()), bool>, 1457a9e65961SEric Fiselier bool 1458a9e65961SEric Fiselier> 1459dc808af3SEric Fiselieroperator<(const _Tp& __v, const optional<_Up>& __x) 1460a9e65961SEric Fiselier{ 1461a9e65961SEric Fiselier return static_cast<bool>(__x) ? __v < *__x : false; 1462a9e65961SEric Fiselier} 1463a9e65961SEric Fiselier 1464dc808af3SEric Fiseliertemplate <class _Tp, class _Up> 1465a9e65961SEric Fiselier_LIBCPP_INLINE_VISIBILITY constexpr 14664e0ea2cfSLouis Dionneenable_if_t< 1467ab3fcc50SArthur O'Dwyer is_convertible_v<decltype(declval<const _Tp&>() <= 1468ab3fcc50SArthur O'Dwyer declval<const _Up&>()), bool>, 1469a9e65961SEric Fiselier bool 1470a9e65961SEric Fiselier> 1471dc808af3SEric Fiselieroperator<=(const optional<_Tp>& __x, const _Up& __v) 1472a9e65961SEric Fiselier{ 1473a9e65961SEric Fiselier return static_cast<bool>(__x) ? *__x <= __v : true; 1474a9e65961SEric Fiselier} 1475a9e65961SEric Fiselier 1476dc808af3SEric Fiseliertemplate <class _Tp, class _Up> 1477a9e65961SEric Fiselier_LIBCPP_INLINE_VISIBILITY constexpr 14784e0ea2cfSLouis Dionneenable_if_t< 1479ab3fcc50SArthur O'Dwyer is_convertible_v<decltype(declval<const _Tp&>() <= 1480ab3fcc50SArthur O'Dwyer declval<const _Up&>()), bool>, 1481a9e65961SEric Fiselier bool 1482a9e65961SEric Fiselier> 1483dc808af3SEric Fiselieroperator<=(const _Tp& __v, const optional<_Up>& __x) 1484a9e65961SEric Fiselier{ 1485a9e65961SEric Fiselier return static_cast<bool>(__x) ? __v <= *__x : false; 1486a9e65961SEric Fiselier} 1487a9e65961SEric Fiselier 1488dc808af3SEric Fiseliertemplate <class _Tp, class _Up> 1489a9e65961SEric Fiselier_LIBCPP_INLINE_VISIBILITY constexpr 14904e0ea2cfSLouis Dionneenable_if_t< 1491ab3fcc50SArthur O'Dwyer is_convertible_v<decltype(declval<const _Tp&>() > 1492ab3fcc50SArthur O'Dwyer declval<const _Up&>()), bool>, 1493a9e65961SEric Fiselier bool 1494a9e65961SEric Fiselier> 1495dc808af3SEric Fiselieroperator>(const optional<_Tp>& __x, const _Up& __v) 1496a9e65961SEric Fiselier{ 1497a9e65961SEric Fiselier return static_cast<bool>(__x) ? *__x > __v : false; 1498a9e65961SEric Fiselier} 1499a9e65961SEric Fiselier 1500dc808af3SEric Fiseliertemplate <class _Tp, class _Up> 1501a9e65961SEric Fiselier_LIBCPP_INLINE_VISIBILITY constexpr 15024e0ea2cfSLouis Dionneenable_if_t< 1503ab3fcc50SArthur O'Dwyer is_convertible_v<decltype(declval<const _Tp&>() > 1504ab3fcc50SArthur O'Dwyer declval<const _Up&>()), bool>, 1505a9e65961SEric Fiselier bool 1506a9e65961SEric Fiselier> 1507dc808af3SEric Fiselieroperator>(const _Tp& __v, const optional<_Up>& __x) 1508a9e65961SEric Fiselier{ 1509a9e65961SEric Fiselier return static_cast<bool>(__x) ? __v > *__x : true; 1510a9e65961SEric Fiselier} 1511a9e65961SEric Fiselier 1512dc808af3SEric Fiseliertemplate <class _Tp, class _Up> 1513a9e65961SEric Fiselier_LIBCPP_INLINE_VISIBILITY constexpr 15144e0ea2cfSLouis Dionneenable_if_t< 1515ab3fcc50SArthur O'Dwyer is_convertible_v<decltype(declval<const _Tp&>() >= 1516ab3fcc50SArthur O'Dwyer declval<const _Up&>()), bool>, 1517a9e65961SEric Fiselier bool 1518a9e65961SEric Fiselier> 1519dc808af3SEric Fiselieroperator>=(const optional<_Tp>& __x, const _Up& __v) 1520a9e65961SEric Fiselier{ 1521a9e65961SEric Fiselier return static_cast<bool>(__x) ? *__x >= __v : false; 1522a9e65961SEric Fiselier} 1523a9e65961SEric Fiselier 1524dc808af3SEric Fiseliertemplate <class _Tp, class _Up> 1525a9e65961SEric Fiselier_LIBCPP_INLINE_VISIBILITY constexpr 15264e0ea2cfSLouis Dionneenable_if_t< 1527ab3fcc50SArthur O'Dwyer is_convertible_v<decltype(declval<const _Tp&>() >= 1528ab3fcc50SArthur O'Dwyer declval<const _Up&>()), bool>, 1529a9e65961SEric Fiselier bool 1530a9e65961SEric Fiselier> 1531dc808af3SEric Fiselieroperator>=(const _Tp& __v, const optional<_Up>& __x) 1532a9e65961SEric Fiselier{ 1533a9e65961SEric Fiselier return static_cast<bool>(__x) ? __v >= *__x : true; 1534a9e65961SEric Fiselier} 1535a9e65961SEric Fiselier 1536a9e65961SEric Fiselier 1537a9e65961SEric Fiseliertemplate <class _Tp> 153854644993SChristopher Di Bellainline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 15394e0ea2cfSLouis Dionneenable_if_t< 1540a9e65961SEric Fiselier is_move_constructible_v<_Tp> && is_swappable_v<_Tp>, 1541a9e65961SEric Fiselier void 1542a9e65961SEric Fiselier> 1543a9e65961SEric Fiselierswap(optional<_Tp>& __x, optional<_Tp>& __y) noexcept(noexcept(__x.swap(__y))) 1544a9e65961SEric Fiselier{ 1545a9e65961SEric Fiselier __x.swap(__y); 1546a9e65961SEric Fiselier} 1547a9e65961SEric Fiselier 1548a9e65961SEric Fiseliertemplate <class _Tp> 1549a9e65961SEric Fiselier_LIBCPP_INLINE_VISIBILITY constexpr 1550a9e65961SEric Fiselieroptional<decay_t<_Tp>> make_optional(_Tp&& __v) 1551a9e65961SEric Fiselier{ 1552a9e65961SEric Fiselier return optional<decay_t<_Tp>>(_VSTD::forward<_Tp>(__v)); 1553a9e65961SEric Fiselier} 1554a9e65961SEric Fiselier 1555a9e65961SEric Fiseliertemplate <class _Tp, class... _Args> 1556a9e65961SEric Fiselier_LIBCPP_INLINE_VISIBILITY constexpr 1557a9e65961SEric Fiselieroptional<_Tp> make_optional(_Args&&... __args) 1558a9e65961SEric Fiselier{ 1559a9e65961SEric Fiselier return optional<_Tp>(in_place, _VSTD::forward<_Args>(__args)...); 1560a9e65961SEric Fiselier} 1561a9e65961SEric Fiselier 1562a9e65961SEric Fiseliertemplate <class _Tp, class _Up, class... _Args> 1563a9e65961SEric Fiselier_LIBCPP_INLINE_VISIBILITY constexpr 1564a9e65961SEric Fiselieroptional<_Tp> make_optional(initializer_list<_Up> __il, _Args&&... __args) 1565a9e65961SEric Fiselier{ 1566a9e65961SEric Fiselier return optional<_Tp>(in_place, __il, _VSTD::forward<_Args>(__args)...); 1567a9e65961SEric Fiselier} 1568a9e65961SEric Fiselier 1569a9e65961SEric Fiseliertemplate <class _Tp> 1570f9127593SEric Fiselierstruct _LIBCPP_TEMPLATE_VIS hash< 1571f9127593SEric Fiselier __enable_hash_helper<optional<_Tp>, remove_const_t<_Tp>> 1572f9127593SEric Fiselier> 1573a9e65961SEric Fiselier{ 1574dc066888SArthur O'Dwyer#if _LIBCPP_STD_VER <= 17 || defined(_LIBCPP_ENABLE_CXX20_REMOVED_BINDER_TYPEDEFS) 1575dc066888SArthur O'Dwyer _LIBCPP_DEPRECATED_IN_CXX17 typedef optional<_Tp> argument_type; 1576dc066888SArthur O'Dwyer _LIBCPP_DEPRECATED_IN_CXX17 typedef size_t result_type; 1577dc066888SArthur O'Dwyer#endif 1578a9e65961SEric Fiselier 1579a9e65961SEric Fiselier _LIBCPP_INLINE_VISIBILITY 1580dc066888SArthur O'Dwyer size_t operator()(const optional<_Tp>& __opt) const 1581a9e65961SEric Fiselier { 1582f9127593SEric Fiselier return static_cast<bool>(__opt) ? hash<remove_const_t<_Tp>>()(*__opt) : 0; 1583a9e65961SEric Fiselier } 1584a9e65961SEric Fiselier}; 1585a9e65961SEric Fiselier 1586a9e65961SEric Fiselier_LIBCPP_END_NAMESPACE_STD 1587a9e65961SEric Fiselier 1588a9e65961SEric Fiselier#endif // _LIBCPP_STD_VER > 14 1589a9e65961SEric Fiselier 1590a9e65961SEric Fiselier#endif // _LIBCPP_OPTIONAL 1591