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> 96a9e65961SEric Fiselier constexpr EXPLICIT optional(U &&); 97a9e65961SEric Fiselier template <class U> 9854644993SChristopher Di Bella EXPLICIT optional(const optional<U> &); // constexpr in C++20 99a9e65961SEric Fiselier template <class U> 10054644993SChristopher Di Bella EXPLICIT 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> 165*faef447eSNikolas Klauser#include <__functional/hash.h> 166*faef447eSNikolas Klauser#include <__functional/invoke.h> 167*faef447eSNikolas Klauser#include <__functional/unary_function.h> 168*faef447eSNikolas Klauser#include <__memory/construct_at.h> 169*faef447eSNikolas Klauser#include <__tuple> 170*faef447eSNikolas Klauser#include <__utility/forward.h> 17152915d78SNikolas Klauser#include <__utility/in_place.h> 172*faef447eSNikolas Klauser#include <__utility/move.h> 17352915d78SNikolas Klauser#include <__utility/swap.h> 1742d0f1fa4SArthur O'Dwyer#include <compare> 175*faef447eSNikolas Klauser#include <functional> // TODO: Remove this include 176a9e65961SEric Fiselier#include <initializer_list> 177a9e65961SEric Fiselier#include <new> 178a9e65961SEric Fiselier#include <stdexcept> 179a9e65961SEric Fiselier#include <type_traits> 180f56972e2SMarshall Clow#include <version> 181a9e65961SEric Fiselier 182169a66eaSNikolas Klauser// TODO: remove these headers 183169a66eaSNikolas Klauser#include <__memory/allocator_arg_t.h> 184169a66eaSNikolas Klauser#include <__memory/uses_allocator.h> 185169a66eaSNikolas Klauser#include <typeinfo> 186169a66eaSNikolas Klauser 187a9e65961SEric Fiselier#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 188a9e65961SEric Fiselier# pragma GCC system_header 189a9e65961SEric Fiselier#endif 190a9e65961SEric Fiselier 191a9e65961SEric Fiseliernamespace std // purposefully not using versioning namespace 192a9e65961SEric Fiselier{ 193a9e65961SEric Fiselier 1948a063df1SLouis Dionneclass _LIBCPP_EXCEPTION_ABI _LIBCPP_AVAILABILITY_BAD_OPTIONAL_ACCESS bad_optional_access 195e29b1ed5SMarshall Clow : public exception 196a9e65961SEric Fiselier{ 197a9e65961SEric Fiselierpublic: 198a9e65961SEric Fiselier // Get the key function ~bad_optional_access() into the dylib 1996a1d0785SMarshall Clow virtual ~bad_optional_access() _NOEXCEPT; 200e29b1ed5SMarshall Clow virtual const char* what() const _NOEXCEPT; 201a9e65961SEric Fiselier}; 202a9e65961SEric Fiselier 203d2b0df35SNikolas Klauser} // namespace std 204a9e65961SEric Fiselier 205a9e65961SEric Fiselier#if _LIBCPP_STD_VER > 14 206a9e65961SEric Fiselier 207a9e65961SEric Fiselier_LIBCPP_BEGIN_NAMESPACE_STD 208a9e65961SEric Fiselier 209a9e65961SEric Fiselier_LIBCPP_NORETURN 210a9e65961SEric Fiselierinline _LIBCPP_INLINE_VISIBILITY 2118a063df1SLouis Dionne_LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS 212a9e65961SEric Fiseliervoid __throw_bad_optional_access() { 213a9e65961SEric Fiselier#ifndef _LIBCPP_NO_EXCEPTIONS 214a9e65961SEric Fiselier throw bad_optional_access(); 215a9e65961SEric Fiselier#else 216a9e65961SEric Fiselier _VSTD::abort(); 217a9e65961SEric Fiselier#endif 218a9e65961SEric Fiselier} 219a9e65961SEric Fiselier 220a9e65961SEric Fiselierstruct nullopt_t 221a9e65961SEric Fiselier{ 222a9e65961SEric Fiselier struct __secret_tag { _LIBCPP_INLINE_VISIBILITY explicit __secret_tag() = default; }; 223a9e65961SEric Fiselier _LIBCPP_INLINE_VISIBILITY constexpr explicit nullopt_t(__secret_tag, __secret_tag) noexcept {} 224a9e65961SEric Fiselier}; 225a9e65961SEric Fiselier 226cb793e1aSLouis Dionneinline constexpr nullopt_t nullopt{nullopt_t::__secret_tag{}, nullopt_t::__secret_tag{}}; 227a9e65961SEric Fiselier 22817cfc57dSNikolas Klauserstruct __optional_construct_from_invoke_tag {}; 22917cfc57dSNikolas Klauser 230a9e65961SEric Fiseliertemplate <class _Tp, bool = is_trivially_destructible<_Tp>::value> 231a9e65961SEric Fiselierstruct __optional_destruct_base; 232a9e65961SEric Fiselier 233a9e65961SEric Fiseliertemplate <class _Tp> 234a9e65961SEric Fiselierstruct __optional_destruct_base<_Tp, false> 235a9e65961SEric Fiselier{ 236a9e65961SEric Fiselier typedef _Tp value_type; 237a9e65961SEric Fiselier static_assert(is_object_v<value_type>, 238a9e65961SEric Fiselier "instantiation of optional with a non-object type is undefined behavior"); 239a9e65961SEric Fiselier union 240a9e65961SEric Fiselier { 241a9e65961SEric Fiselier char __null_state_; 242a9e65961SEric Fiselier value_type __val_; 243a9e65961SEric Fiselier }; 244a9e65961SEric Fiselier bool __engaged_; 245a9e65961SEric Fiselier 246a9e65961SEric Fiselier _LIBCPP_INLINE_VISIBILITY 24754644993SChristopher Di Bella _LIBCPP_CONSTEXPR_AFTER_CXX17 ~__optional_destruct_base() 248a9e65961SEric Fiselier { 249a9e65961SEric Fiselier if (__engaged_) 250a9e65961SEric Fiselier __val_.~value_type(); 251a9e65961SEric Fiselier } 252a9e65961SEric Fiselier 253a9e65961SEric Fiselier _LIBCPP_INLINE_VISIBILITY 254a9e65961SEric Fiselier constexpr __optional_destruct_base() noexcept 255a9e65961SEric Fiselier : __null_state_(), 256a9e65961SEric Fiselier __engaged_(false) {} 257a9e65961SEric Fiselier 258a9e65961SEric Fiselier template <class... _Args> 259a9e65961SEric Fiselier _LIBCPP_INLINE_VISIBILITY 260a9e65961SEric Fiselier constexpr explicit __optional_destruct_base(in_place_t, _Args&&... __args) 261a9e65961SEric Fiselier : __val_(_VSTD::forward<_Args>(__args)...), 262a9e65961SEric Fiselier __engaged_(true) {} 263a9e65961SEric Fiselier 26417cfc57dSNikolas Klauser#if _LIBCPP_STD_VER > 20 26517cfc57dSNikolas Klauser template <class _Fp, class... _Args> 26617cfc57dSNikolas Klauser _LIBCPP_HIDE_FROM_ABI 26717cfc57dSNikolas Klauser constexpr __optional_destruct_base(__optional_construct_from_invoke_tag, _Fp&& __f, _Args&&... __args) 26817cfc57dSNikolas Klauser : __val_(_VSTD::invoke(_VSTD::forward<_Fp>(__f), _VSTD::forward<_Args>(__args)...)), __engaged_(true) {} 26917cfc57dSNikolas Klauser#endif 27017cfc57dSNikolas Klauser 271a9e65961SEric Fiselier _LIBCPP_INLINE_VISIBILITY 27254644993SChristopher Di Bella _LIBCPP_CONSTEXPR_AFTER_CXX17 void reset() noexcept 273a9e65961SEric Fiselier { 274a9e65961SEric Fiselier if (__engaged_) 275a9e65961SEric Fiselier { 276a9e65961SEric Fiselier __val_.~value_type(); 277a9e65961SEric Fiselier __engaged_ = false; 278a9e65961SEric Fiselier } 279a9e65961SEric Fiselier } 280a9e65961SEric Fiselier}; 281a9e65961SEric Fiselier 282a9e65961SEric Fiseliertemplate <class _Tp> 283a9e65961SEric Fiselierstruct __optional_destruct_base<_Tp, true> 284a9e65961SEric Fiselier{ 285a9e65961SEric Fiselier typedef _Tp value_type; 286a9e65961SEric Fiselier static_assert(is_object_v<value_type>, 287a9e65961SEric Fiselier "instantiation of optional with a non-object type is undefined behavior"); 288a9e65961SEric Fiselier union 289a9e65961SEric Fiselier { 290a9e65961SEric Fiselier char __null_state_; 291a9e65961SEric Fiselier value_type __val_; 292a9e65961SEric Fiselier }; 293a9e65961SEric Fiselier bool __engaged_; 294a9e65961SEric Fiselier 295a9e65961SEric Fiselier _LIBCPP_INLINE_VISIBILITY 296a9e65961SEric Fiselier constexpr __optional_destruct_base() noexcept 297a9e65961SEric Fiselier : __null_state_(), 298a9e65961SEric Fiselier __engaged_(false) {} 299a9e65961SEric Fiselier 300a9e65961SEric Fiselier template <class... _Args> 301a9e65961SEric Fiselier _LIBCPP_INLINE_VISIBILITY 302a9e65961SEric Fiselier constexpr explicit __optional_destruct_base(in_place_t, _Args&&... __args) 303a9e65961SEric Fiselier : __val_(_VSTD::forward<_Args>(__args)...), 304a9e65961SEric Fiselier __engaged_(true) {} 305a9e65961SEric Fiselier 30617cfc57dSNikolas Klauser#if _LIBCPP_STD_VER > 20 30717cfc57dSNikolas Klauser template <class _Fp, class... _Args> 30817cfc57dSNikolas Klauser _LIBCPP_HIDE_FROM_ABI 30917cfc57dSNikolas Klauser constexpr __optional_destruct_base(__optional_construct_from_invoke_tag, _Fp&& __f, _Args&&... __args) 31017cfc57dSNikolas Klauser : __val_(_VSTD::invoke(_VSTD::forward<_Fp>(__f), _VSTD::forward<_Args>(__args)...)), __engaged_(true) {} 31117cfc57dSNikolas Klauser#endif 31217cfc57dSNikolas Klauser 313a9e65961SEric Fiselier _LIBCPP_INLINE_VISIBILITY 31454644993SChristopher Di Bella _LIBCPP_CONSTEXPR_AFTER_CXX17 void reset() noexcept 315a9e65961SEric Fiselier { 316a9e65961SEric Fiselier if (__engaged_) 317a9e65961SEric Fiselier { 318a9e65961SEric Fiselier __engaged_ = false; 319a9e65961SEric Fiselier } 320a9e65961SEric Fiselier } 321a9e65961SEric Fiselier}; 322a9e65961SEric Fiselier 323a9e65961SEric Fiseliertemplate <class _Tp, bool = is_reference<_Tp>::value> 324a9e65961SEric Fiselierstruct __optional_storage_base : __optional_destruct_base<_Tp> 325a9e65961SEric Fiselier{ 326a9e65961SEric Fiselier using __base = __optional_destruct_base<_Tp>; 327a9e65961SEric Fiselier using value_type = _Tp; 328a9e65961SEric Fiselier using __base::__base; 329a9e65961SEric Fiselier 330a9e65961SEric Fiselier _LIBCPP_INLINE_VISIBILITY 331a9e65961SEric Fiselier constexpr bool has_value() const noexcept 332a9e65961SEric Fiselier { 333a9e65961SEric Fiselier return this->__engaged_; 334a9e65961SEric Fiselier } 335a9e65961SEric Fiselier 336a9e65961SEric Fiselier _LIBCPP_INLINE_VISIBILITY 337a9e65961SEric Fiselier constexpr value_type& __get() & noexcept 338a9e65961SEric Fiselier { 339a9e65961SEric Fiselier return this->__val_; 340a9e65961SEric Fiselier } 341a9e65961SEric Fiselier _LIBCPP_INLINE_VISIBILITY 342a9e65961SEric Fiselier constexpr const value_type& __get() const& noexcept 343a9e65961SEric Fiselier { 344a9e65961SEric Fiselier return this->__val_; 345a9e65961SEric Fiselier } 346a9e65961SEric Fiselier _LIBCPP_INLINE_VISIBILITY 347a9e65961SEric Fiselier constexpr value_type&& __get() && noexcept 348a9e65961SEric Fiselier { 349a9e65961SEric Fiselier return _VSTD::move(this->__val_); 350a9e65961SEric Fiselier } 351a9e65961SEric Fiselier _LIBCPP_INLINE_VISIBILITY 352a9e65961SEric Fiselier constexpr const value_type&& __get() const&& noexcept 353a9e65961SEric Fiselier { 354a9e65961SEric Fiselier return _VSTD::move(this->__val_); 355a9e65961SEric Fiselier } 356a9e65961SEric Fiselier 357a9e65961SEric Fiselier template <class... _Args> 358a9e65961SEric Fiselier _LIBCPP_INLINE_VISIBILITY 35954644993SChristopher Di Bella _LIBCPP_CONSTEXPR_AFTER_CXX17 void __construct(_Args&&... __args) 360a9e65961SEric Fiselier { 361a9e65961SEric Fiselier _LIBCPP_ASSERT(!has_value(), "__construct called for engaged __optional_storage"); 36254644993SChristopher Di Bella#if _LIBCPP_STD_VER > 17 36354644993SChristopher Di Bella _VSTD::construct_at(_VSTD::addressof(this->__val_), _VSTD::forward<_Args>(__args)...); 36454644993SChristopher Di Bella#else 365a9e65961SEric Fiselier ::new ((void*)_VSTD::addressof(this->__val_)) value_type(_VSTD::forward<_Args>(__args)...); 36654644993SChristopher Di Bella#endif 367a9e65961SEric Fiselier this->__engaged_ = true; 368a9e65961SEric Fiselier } 369a9e65961SEric Fiselier 370a9e65961SEric Fiselier template <class _That> 371a9e65961SEric Fiselier _LIBCPP_INLINE_VISIBILITY 37254644993SChristopher Di Bella _LIBCPP_CONSTEXPR_AFTER_CXX17 void __construct_from(_That&& __opt) 373a9e65961SEric Fiselier { 374a9e65961SEric Fiselier if (__opt.has_value()) 375a9e65961SEric Fiselier __construct(_VSTD::forward<_That>(__opt).__get()); 376a9e65961SEric Fiselier } 377a9e65961SEric Fiselier 378a9e65961SEric Fiselier template <class _That> 379a9e65961SEric Fiselier _LIBCPP_INLINE_VISIBILITY 38054644993SChristopher Di Bella _LIBCPP_CONSTEXPR_AFTER_CXX17 void __assign_from(_That&& __opt) 381a9e65961SEric Fiselier { 382a9e65961SEric Fiselier if (this->__engaged_ == __opt.has_value()) 383a9e65961SEric Fiselier { 384a9e65961SEric Fiselier if (this->__engaged_) 385a9e65961SEric Fiselier this->__val_ = _VSTD::forward<_That>(__opt).__get(); 386a9e65961SEric Fiselier } 387a9e65961SEric Fiselier else 388a9e65961SEric Fiselier { 389a9e65961SEric Fiselier if (this->__engaged_) 390a9e65961SEric Fiselier this->reset(); 391a9e65961SEric Fiselier else 392a9e65961SEric Fiselier __construct(_VSTD::forward<_That>(__opt).__get()); 393a9e65961SEric Fiselier } 394a9e65961SEric Fiselier } 395a9e65961SEric Fiselier}; 396a9e65961SEric Fiselier 397a9e65961SEric Fiselier// optional<T&> is currently required ill-formed, however it may to be in the 398a9e65961SEric Fiselier// future. For this reason it has already been implemented to ensure we can 399a9e65961SEric Fiselier// make the change in an ABI compatible manner. 400a9e65961SEric Fiseliertemplate <class _Tp> 401a9e65961SEric Fiselierstruct __optional_storage_base<_Tp, true> 402a9e65961SEric Fiselier{ 403a9e65961SEric Fiselier using value_type = _Tp; 404a9e65961SEric Fiselier using __raw_type = remove_reference_t<_Tp>; 405a9e65961SEric Fiselier __raw_type* __value_; 406a9e65961SEric Fiselier 407a9e65961SEric Fiselier template <class _Up> 408a9e65961SEric Fiselier static constexpr bool __can_bind_reference() { 409a9e65961SEric Fiselier using _RawUp = typename remove_reference<_Up>::type; 410a9e65961SEric Fiselier using _UpPtr = _RawUp*; 411a9e65961SEric Fiselier using _RawTp = typename remove_reference<_Tp>::type; 412a9e65961SEric Fiselier using _TpPtr = _RawTp*; 413a9e65961SEric Fiselier using _CheckLValueArg = integral_constant<bool, 414a9e65961SEric Fiselier (is_lvalue_reference<_Up>::value && is_convertible<_UpPtr, _TpPtr>::value) 415a9e65961SEric Fiselier || is_same<_RawUp, reference_wrapper<_RawTp>>::value 416a9e65961SEric Fiselier || is_same<_RawUp, reference_wrapper<typename remove_const<_RawTp>::type>>::value 417a9e65961SEric Fiselier >; 418a9e65961SEric Fiselier return (is_lvalue_reference<_Tp>::value && _CheckLValueArg::value) 419a9e65961SEric Fiselier || (is_rvalue_reference<_Tp>::value && !is_lvalue_reference<_Up>::value && 420a9e65961SEric Fiselier is_convertible<_UpPtr, _TpPtr>::value); 421a9e65961SEric Fiselier } 422a9e65961SEric Fiselier 423a9e65961SEric Fiselier _LIBCPP_INLINE_VISIBILITY 424a9e65961SEric Fiselier constexpr __optional_storage_base() noexcept 425a9e65961SEric Fiselier : __value_(nullptr) {} 426a9e65961SEric Fiselier 427a9e65961SEric Fiselier template <class _UArg> 428a9e65961SEric Fiselier _LIBCPP_INLINE_VISIBILITY 429a9e65961SEric Fiselier constexpr explicit __optional_storage_base(in_place_t, _UArg&& __uarg) 430a9e65961SEric Fiselier : __value_(_VSTD::addressof(__uarg)) 431a9e65961SEric Fiselier { 432a9e65961SEric Fiselier static_assert(__can_bind_reference<_UArg>(), 433a9e65961SEric Fiselier "Attempted to construct a reference element in tuple from a " 434a9e65961SEric Fiselier "possible temporary"); 435a9e65961SEric Fiselier } 436a9e65961SEric Fiselier 437a9e65961SEric Fiselier _LIBCPP_INLINE_VISIBILITY 43854644993SChristopher Di Bella _LIBCPP_CONSTEXPR_AFTER_CXX17 void reset() noexcept { __value_ = nullptr; } 439a9e65961SEric Fiselier 440a9e65961SEric Fiselier _LIBCPP_INLINE_VISIBILITY 441a9e65961SEric Fiselier constexpr bool has_value() const noexcept 442a9e65961SEric Fiselier { return __value_ != nullptr; } 443a9e65961SEric Fiselier 444a9e65961SEric Fiselier _LIBCPP_INLINE_VISIBILITY 445a9e65961SEric Fiselier constexpr value_type& __get() const& noexcept 446a9e65961SEric Fiselier { return *__value_; } 447a9e65961SEric Fiselier 448a9e65961SEric Fiselier _LIBCPP_INLINE_VISIBILITY 449a9e65961SEric Fiselier constexpr value_type&& __get() const&& noexcept 450a9e65961SEric Fiselier { return _VSTD::forward<value_type>(*__value_); } 451a9e65961SEric Fiselier 452a9e65961SEric Fiselier template <class _UArg> 453a9e65961SEric Fiselier _LIBCPP_INLINE_VISIBILITY 45454644993SChristopher Di Bella _LIBCPP_CONSTEXPR_AFTER_CXX17 void __construct(_UArg&& __val) 455a9e65961SEric Fiselier { 456a9e65961SEric Fiselier _LIBCPP_ASSERT(!has_value(), "__construct called for engaged __optional_storage"); 457a9e65961SEric Fiselier static_assert(__can_bind_reference<_UArg>(), 458a9e65961SEric Fiselier "Attempted to construct a reference element in tuple from a " 459a9e65961SEric Fiselier "possible temporary"); 460a9e65961SEric Fiselier __value_ = _VSTD::addressof(__val); 461a9e65961SEric Fiselier } 462a9e65961SEric Fiselier 463a9e65961SEric Fiselier template <class _That> 464a9e65961SEric Fiselier _LIBCPP_INLINE_VISIBILITY 46554644993SChristopher Di Bella _LIBCPP_CONSTEXPR_AFTER_CXX17 void __construct_from(_That&& __opt) 466a9e65961SEric Fiselier { 467a9e65961SEric Fiselier if (__opt.has_value()) 468a9e65961SEric Fiselier __construct(_VSTD::forward<_That>(__opt).__get()); 469a9e65961SEric Fiselier } 470a9e65961SEric Fiselier 471a9e65961SEric Fiselier template <class _That> 472a9e65961SEric Fiselier _LIBCPP_INLINE_VISIBILITY 47354644993SChristopher Di Bella _LIBCPP_CONSTEXPR_AFTER_CXX17 void __assign_from(_That&& __opt) 474a9e65961SEric Fiselier { 475a9e65961SEric Fiselier if (has_value() == __opt.has_value()) 476a9e65961SEric Fiselier { 477a9e65961SEric Fiselier if (has_value()) 478a9e65961SEric Fiselier *__value_ = _VSTD::forward<_That>(__opt).__get(); 479a9e65961SEric Fiselier } 480a9e65961SEric Fiselier else 481a9e65961SEric Fiselier { 482a9e65961SEric Fiselier if (has_value()) 483a9e65961SEric Fiselier reset(); 484a9e65961SEric Fiselier else 485a9e65961SEric Fiselier __construct(_VSTD::forward<_That>(__opt).__get()); 486a9e65961SEric Fiselier } 487a9e65961SEric Fiselier } 488a9e65961SEric Fiselier}; 489a9e65961SEric Fiselier 490f2d571c8SCasey Cartertemplate <class _Tp, bool = is_trivially_copy_constructible<_Tp>::value> 491f2d571c8SCasey Carterstruct __optional_copy_base : __optional_storage_base<_Tp> 492a9e65961SEric Fiselier{ 493a9e65961SEric Fiselier using __optional_storage_base<_Tp>::__optional_storage_base; 494a9e65961SEric Fiselier}; 495a9e65961SEric Fiselier 496a9e65961SEric Fiseliertemplate <class _Tp> 497f2d571c8SCasey Carterstruct __optional_copy_base<_Tp, false> : __optional_storage_base<_Tp> 498a9e65961SEric Fiselier{ 499a9e65961SEric Fiselier using __optional_storage_base<_Tp>::__optional_storage_base; 500a9e65961SEric Fiselier 501a9e65961SEric Fiselier _LIBCPP_INLINE_VISIBILITY 502f2d571c8SCasey Carter __optional_copy_base() = default; 503a9e65961SEric Fiselier 504a9e65961SEric Fiselier _LIBCPP_INLINE_VISIBILITY 50554644993SChristopher Di Bella _LIBCPP_CONSTEXPR_AFTER_CXX17 __optional_copy_base(const __optional_copy_base& __opt) 506a9e65961SEric Fiselier { 507a9e65961SEric Fiselier this->__construct_from(__opt); 508a9e65961SEric Fiselier } 509a9e65961SEric Fiselier 510a9e65961SEric Fiselier _LIBCPP_INLINE_VISIBILITY 511f2d571c8SCasey Carter __optional_copy_base(__optional_copy_base&&) = default; 512f2d571c8SCasey Carter _LIBCPP_INLINE_VISIBILITY 513f2d571c8SCasey Carter __optional_copy_base& operator=(const __optional_copy_base&) = default; 514f2d571c8SCasey Carter _LIBCPP_INLINE_VISIBILITY 515f2d571c8SCasey Carter __optional_copy_base& operator=(__optional_copy_base&&) = default; 516f2d571c8SCasey Carter}; 517f2d571c8SCasey Carter 518f2d571c8SCasey Cartertemplate <class _Tp, bool = is_trivially_move_constructible<_Tp>::value> 519f2d571c8SCasey Carterstruct __optional_move_base : __optional_copy_base<_Tp> 520f2d571c8SCasey Carter{ 521f2d571c8SCasey Carter using __optional_copy_base<_Tp>::__optional_copy_base; 522f2d571c8SCasey Carter}; 523f2d571c8SCasey Carter 524f2d571c8SCasey Cartertemplate <class _Tp> 525f2d571c8SCasey Carterstruct __optional_move_base<_Tp, false> : __optional_copy_base<_Tp> 526f2d571c8SCasey Carter{ 527f2d571c8SCasey Carter using value_type = _Tp; 528f2d571c8SCasey Carter using __optional_copy_base<_Tp>::__optional_copy_base; 529f2d571c8SCasey Carter 530f2d571c8SCasey Carter _LIBCPP_INLINE_VISIBILITY 531f2d571c8SCasey Carter __optional_move_base() = default; 532f2d571c8SCasey Carter _LIBCPP_INLINE_VISIBILITY 533f2d571c8SCasey Carter __optional_move_base(const __optional_move_base&) = default; 534f2d571c8SCasey Carter 535f2d571c8SCasey Carter _LIBCPP_INLINE_VISIBILITY 53654644993SChristopher Di Bella _LIBCPP_CONSTEXPR_AFTER_CXX17 __optional_move_base(__optional_move_base&& __opt) 537a9e65961SEric Fiselier noexcept(is_nothrow_move_constructible_v<value_type>) 538a9e65961SEric Fiselier { 539a9e65961SEric Fiselier this->__construct_from(_VSTD::move(__opt)); 540a9e65961SEric Fiselier } 541a9e65961SEric Fiselier 542a9e65961SEric Fiselier _LIBCPP_INLINE_VISIBILITY 543f2d571c8SCasey Carter __optional_move_base& operator=(const __optional_move_base&) = default; 544f2d571c8SCasey Carter _LIBCPP_INLINE_VISIBILITY 545f2d571c8SCasey Carter __optional_move_base& operator=(__optional_move_base&&) = default; 546f2d571c8SCasey Carter}; 547f2d571c8SCasey Carter 548f2d571c8SCasey Cartertemplate <class _Tp, bool = 549f2d571c8SCasey Carter is_trivially_destructible<_Tp>::value && 550f2d571c8SCasey Carter is_trivially_copy_constructible<_Tp>::value && 551f2d571c8SCasey Carter is_trivially_copy_assignable<_Tp>::value> 552f2d571c8SCasey Carterstruct __optional_copy_assign_base : __optional_move_base<_Tp> 553f2d571c8SCasey Carter{ 554f2d571c8SCasey Carter using __optional_move_base<_Tp>::__optional_move_base; 555f2d571c8SCasey Carter}; 556f2d571c8SCasey Carter 557f2d571c8SCasey Cartertemplate <class _Tp> 558f2d571c8SCasey Carterstruct __optional_copy_assign_base<_Tp, false> : __optional_move_base<_Tp> 559f2d571c8SCasey Carter{ 560f2d571c8SCasey Carter using __optional_move_base<_Tp>::__optional_move_base; 561f2d571c8SCasey Carter 562f2d571c8SCasey Carter _LIBCPP_INLINE_VISIBILITY 563f2d571c8SCasey Carter __optional_copy_assign_base() = default; 564f2d571c8SCasey Carter _LIBCPP_INLINE_VISIBILITY 565f2d571c8SCasey Carter __optional_copy_assign_base(const __optional_copy_assign_base&) = default; 566f2d571c8SCasey Carter _LIBCPP_INLINE_VISIBILITY 567f2d571c8SCasey Carter __optional_copy_assign_base(__optional_copy_assign_base&&) = default; 568f2d571c8SCasey Carter 569f2d571c8SCasey Carter _LIBCPP_INLINE_VISIBILITY 57054644993SChristopher Di Bella _LIBCPP_CONSTEXPR_AFTER_CXX17 __optional_copy_assign_base& operator=(const __optional_copy_assign_base& __opt) 571a9e65961SEric Fiselier { 572a9e65961SEric Fiselier this->__assign_from(__opt); 573a9e65961SEric Fiselier return *this; 574a9e65961SEric Fiselier } 575a9e65961SEric Fiselier 576a9e65961SEric Fiselier _LIBCPP_INLINE_VISIBILITY 577f2d571c8SCasey Carter __optional_copy_assign_base& operator=(__optional_copy_assign_base&&) = default; 578f2d571c8SCasey Carter}; 579f2d571c8SCasey Carter 580f2d571c8SCasey Cartertemplate <class _Tp, bool = 581f2d571c8SCasey Carter is_trivially_destructible<_Tp>::value && 582f2d571c8SCasey Carter is_trivially_move_constructible<_Tp>::value && 583f2d571c8SCasey Carter is_trivially_move_assignable<_Tp>::value> 584f2d571c8SCasey Carterstruct __optional_move_assign_base : __optional_copy_assign_base<_Tp> 585f2d571c8SCasey Carter{ 586f2d571c8SCasey Carter using __optional_copy_assign_base<_Tp>::__optional_copy_assign_base; 587f2d571c8SCasey Carter}; 588f2d571c8SCasey Carter 589f2d571c8SCasey Cartertemplate <class _Tp> 590f2d571c8SCasey Carterstruct __optional_move_assign_base<_Tp, false> : __optional_copy_assign_base<_Tp> 591f2d571c8SCasey Carter{ 592f2d571c8SCasey Carter using value_type = _Tp; 593f2d571c8SCasey Carter using __optional_copy_assign_base<_Tp>::__optional_copy_assign_base; 594f2d571c8SCasey Carter 595f2d571c8SCasey Carter _LIBCPP_INLINE_VISIBILITY 596f2d571c8SCasey Carter __optional_move_assign_base() = default; 597f2d571c8SCasey Carter _LIBCPP_INLINE_VISIBILITY 598f2d571c8SCasey Carter __optional_move_assign_base(const __optional_move_assign_base& __opt) = default; 599f2d571c8SCasey Carter _LIBCPP_INLINE_VISIBILITY 600f2d571c8SCasey Carter __optional_move_assign_base(__optional_move_assign_base&&) = default; 601f2d571c8SCasey Carter _LIBCPP_INLINE_VISIBILITY 602f2d571c8SCasey Carter __optional_move_assign_base& operator=(const __optional_move_assign_base&) = default; 603f2d571c8SCasey Carter 604f2d571c8SCasey Carter _LIBCPP_INLINE_VISIBILITY 60554644993SChristopher Di Bella _LIBCPP_CONSTEXPR_AFTER_CXX17 __optional_move_assign_base& operator=(__optional_move_assign_base&& __opt) 606a9e65961SEric Fiselier noexcept(is_nothrow_move_assignable_v<value_type> && 607a9e65961SEric Fiselier is_nothrow_move_constructible_v<value_type>) 608a9e65961SEric Fiselier { 609a9e65961SEric Fiselier this->__assign_from(_VSTD::move(__opt)); 610a9e65961SEric Fiselier return *this; 611a9e65961SEric Fiselier } 612a9e65961SEric Fiselier}; 613a9e65961SEric Fiselier 614a9e65961SEric Fiseliertemplate <class _Tp> 615a9e65961SEric Fiselierusing __optional_sfinae_ctor_base_t = __sfinae_ctor_base< 616a9e65961SEric Fiselier is_copy_constructible<_Tp>::value, 617a9e65961SEric Fiselier is_move_constructible<_Tp>::value 618a9e65961SEric Fiselier>; 619a9e65961SEric Fiselier 620a9e65961SEric Fiseliertemplate <class _Tp> 621a9e65961SEric Fiselierusing __optional_sfinae_assign_base_t = __sfinae_assign_base< 622a9e65961SEric Fiselier (is_copy_constructible<_Tp>::value && is_copy_assignable<_Tp>::value), 623a9e65961SEric Fiselier (is_move_constructible<_Tp>::value && is_move_assignable<_Tp>::value) 624a9e65961SEric Fiselier>; 625a9e65961SEric Fiselier 626a9e65961SEric Fiseliertemplate<class _Tp> 62717cfc57dSNikolas Klauserclass optional; 62817cfc57dSNikolas Klausertemplate <class _Tp> 62917cfc57dSNikolas Klauserstruct __is_std_optional : false_type {}; 63017cfc57dSNikolas Klausertemplate <class _Tp> struct __is_std_optional<optional<_Tp>> : true_type {}; 63117cfc57dSNikolas Klauser 63217cfc57dSNikolas Klausertemplate <class _Tp> 633a9e65961SEric Fiselierclass optional 634f2d571c8SCasey Carter : private __optional_move_assign_base<_Tp> 635a9e65961SEric Fiselier , private __optional_sfinae_ctor_base_t<_Tp> 636a9e65961SEric Fiselier , private __optional_sfinae_assign_base_t<_Tp> 637a9e65961SEric Fiselier{ 638f2d571c8SCasey Carter using __base = __optional_move_assign_base<_Tp>; 639a9e65961SEric Fiselierpublic: 640a9e65961SEric Fiselier using value_type = _Tp; 641a9e65961SEric Fiselier 642a9e65961SEric Fiselierprivate: 643a9e65961SEric Fiselier // Disable the reference extension using this static assert. 64436db4898SMarshall Clow static_assert(!is_same_v<__uncvref_t<value_type>, in_place_t>, 645a9e65961SEric Fiselier "instantiation of optional with in_place_t is ill-formed"); 646a9e65961SEric Fiselier static_assert(!is_same_v<__uncvref_t<value_type>, nullopt_t>, 647a9e65961SEric Fiselier "instantiation of optional with nullopt_t is ill-formed"); 648a9e65961SEric Fiselier static_assert(!is_reference_v<value_type>, 649a9e65961SEric Fiselier "instantiation of optional with a reference type is ill-formed"); 650a9e65961SEric Fiselier static_assert(is_destructible_v<value_type>, 651a9e65961SEric Fiselier "instantiation of optional with a non-destructible type is ill-formed"); 65236db4898SMarshall Clow static_assert(!is_array_v<value_type>, 65336db4898SMarshall Clow "instantiation of optional with an array type is ill-formed"); 654a9e65961SEric Fiselier 655a9e65961SEric Fiselier // LWG2756: conditionally explicit conversion from _Up 656a9e65961SEric Fiselier struct _CheckOptionalArgsConstructor { 657a9e65961SEric Fiselier template <class _Up> 658a9e65961SEric Fiselier static constexpr bool __enable_implicit() { 659a9e65961SEric Fiselier return is_constructible_v<_Tp, _Up&&> && 660a9e65961SEric Fiselier is_convertible_v<_Up&&, _Tp>; 661a9e65961SEric Fiselier } 662a9e65961SEric Fiselier 663a9e65961SEric Fiselier template <class _Up> 664a9e65961SEric Fiselier static constexpr bool __enable_explicit() { 665a9e65961SEric Fiselier return is_constructible_v<_Tp, _Up&&> && 666a9e65961SEric Fiselier !is_convertible_v<_Up&&, _Tp>; 667a9e65961SEric Fiselier } 668a9e65961SEric Fiselier }; 669a9e65961SEric Fiselier template <class _Up> 6703359a17bSEric Fiselier using _CheckOptionalArgsCtor = _If< 6713359a17bSEric Fiselier _IsNotSame<__uncvref_t<_Up>, in_place_t>::value && 6723359a17bSEric Fiselier _IsNotSame<__uncvref_t<_Up>, optional>::value, 673a9e65961SEric Fiselier _CheckOptionalArgsConstructor, 674a9e65961SEric Fiselier __check_tuple_constructor_fail 675a9e65961SEric Fiselier >; 676a9e65961SEric Fiselier template <class _QualUp> 677a9e65961SEric Fiselier struct _CheckOptionalLikeConstructor { 678a9e65961SEric Fiselier template <class _Up, class _Opt = optional<_Up>> 6793359a17bSEric Fiselier using __check_constructible_from_opt = _Or< 680a9e65961SEric Fiselier is_constructible<_Tp, _Opt&>, 681a9e65961SEric Fiselier is_constructible<_Tp, _Opt const&>, 682a9e65961SEric Fiselier is_constructible<_Tp, _Opt&&>, 683a9e65961SEric Fiselier is_constructible<_Tp, _Opt const&&>, 684a9e65961SEric Fiselier is_convertible<_Opt&, _Tp>, 685a9e65961SEric Fiselier is_convertible<_Opt const&, _Tp>, 686a9e65961SEric Fiselier is_convertible<_Opt&&, _Tp>, 687a9e65961SEric Fiselier is_convertible<_Opt const&&, _Tp> 688a9e65961SEric Fiselier >; 689a9e65961SEric Fiselier template <class _Up, class _Opt = optional<_Up>> 6903359a17bSEric Fiselier using __check_assignable_from_opt = _Or< 691a9e65961SEric Fiselier is_assignable<_Tp&, _Opt&>, 692a9e65961SEric Fiselier is_assignable<_Tp&, _Opt const&>, 693a9e65961SEric Fiselier is_assignable<_Tp&, _Opt&&>, 694a9e65961SEric Fiselier is_assignable<_Tp&, _Opt const&&> 695a9e65961SEric Fiselier >; 696a9e65961SEric Fiselier template <class _Up, class _QUp = _QualUp> 697a9e65961SEric Fiselier static constexpr bool __enable_implicit() { 698a9e65961SEric Fiselier return is_convertible<_QUp, _Tp>::value && 699a9e65961SEric Fiselier !__check_constructible_from_opt<_Up>::value; 700a9e65961SEric Fiselier } 701a9e65961SEric Fiselier template <class _Up, class _QUp = _QualUp> 702a9e65961SEric Fiselier static constexpr bool __enable_explicit() { 703a9e65961SEric Fiselier return !is_convertible<_QUp, _Tp>::value && 704a9e65961SEric Fiselier !__check_constructible_from_opt<_Up>::value; 705a9e65961SEric Fiselier } 706a9e65961SEric Fiselier template <class _Up, class _QUp = _QualUp> 707a9e65961SEric Fiselier static constexpr bool __enable_assign() { 708b6f19174SArthur O'Dwyer // Construction and assignability of _QUp to _Tp has already been 709a9e65961SEric Fiselier // checked. 710a9e65961SEric Fiselier return !__check_constructible_from_opt<_Up>::value && 711a9e65961SEric Fiselier !__check_assignable_from_opt<_Up>::value; 712a9e65961SEric Fiselier } 713a9e65961SEric Fiselier }; 714a9e65961SEric Fiselier 715a9e65961SEric Fiselier template <class _Up, class _QualUp> 7163359a17bSEric Fiselier using _CheckOptionalLikeCtor = _If< 7173359a17bSEric Fiselier _And< 7183359a17bSEric Fiselier _IsNotSame<_Up, _Tp>, 719a9e65961SEric Fiselier is_constructible<_Tp, _QualUp> 720a9e65961SEric Fiselier >::value, 721a9e65961SEric Fiselier _CheckOptionalLikeConstructor<_QualUp>, 722a9e65961SEric Fiselier __check_tuple_constructor_fail 723a9e65961SEric Fiselier >; 724a9e65961SEric Fiselier template <class _Up, class _QualUp> 7253359a17bSEric Fiselier using _CheckOptionalLikeAssign = _If< 7263359a17bSEric Fiselier _And< 7273359a17bSEric Fiselier _IsNotSame<_Up, _Tp>, 728a9e65961SEric Fiselier is_constructible<_Tp, _QualUp>, 729a9e65961SEric Fiselier is_assignable<_Tp&, _QualUp> 730a9e65961SEric Fiselier >::value, 731a9e65961SEric Fiselier _CheckOptionalLikeConstructor<_QualUp>, 732a9e65961SEric Fiselier __check_tuple_constructor_fail 733a9e65961SEric Fiselier >; 73417cfc57dSNikolas Klauser 735a9e65961SEric Fiselierpublic: 736a9e65961SEric Fiselier 737a9e65961SEric Fiselier _LIBCPP_INLINE_VISIBILITY constexpr optional() noexcept {} 738c1bcd4c1SMarshall Clow _LIBCPP_INLINE_VISIBILITY constexpr optional(const optional&) = default; 739c1bcd4c1SMarshall Clow _LIBCPP_INLINE_VISIBILITY constexpr optional(optional&&) = default; 740a9e65961SEric Fiselier _LIBCPP_INLINE_VISIBILITY constexpr optional(nullopt_t) noexcept {} 741a9e65961SEric Fiselier 7424e0ea2cfSLouis Dionne template <class _InPlaceT, class... _Args, class = enable_if_t< 7433359a17bSEric Fiselier _And< 7443359a17bSEric Fiselier _IsSame<_InPlaceT, in_place_t>, 74586af6f50SEric Fiselier is_constructible<value_type, _Args...> 74686af6f50SEric Fiselier >::value 74786af6f50SEric Fiselier > 748a9e65961SEric Fiselier > 749a9e65961SEric Fiselier _LIBCPP_INLINE_VISIBILITY 75086af6f50SEric Fiselier constexpr explicit optional(_InPlaceT, _Args&&... __args) 751a9e65961SEric Fiselier : __base(in_place, _VSTD::forward<_Args>(__args)...) {} 752a9e65961SEric Fiselier 7534e0ea2cfSLouis Dionne template <class _Up, class... _Args, class = enable_if_t< 754a9e65961SEric Fiselier is_constructible_v<value_type, initializer_list<_Up>&, _Args...>> 755a9e65961SEric Fiselier > 756a9e65961SEric Fiselier _LIBCPP_INLINE_VISIBILITY 757a9e65961SEric Fiselier constexpr explicit optional(in_place_t, initializer_list<_Up> __il, _Args&&... __args) 758a9e65961SEric Fiselier : __base(in_place, __il, _VSTD::forward<_Args>(__args)...) {} 759a9e65961SEric Fiselier 7604e0ea2cfSLouis Dionne template <class _Up = value_type, enable_if_t< 761a9e65961SEric Fiselier _CheckOptionalArgsCtor<_Up>::template __enable_implicit<_Up>() 762a9e65961SEric Fiselier , int> = 0> 763a9e65961SEric Fiselier _LIBCPP_INLINE_VISIBILITY 764a9e65961SEric Fiselier constexpr optional(_Up&& __v) 765a9e65961SEric Fiselier : __base(in_place, _VSTD::forward<_Up>(__v)) {} 766a9e65961SEric Fiselier 7674e0ea2cfSLouis Dionne template <class _Up, enable_if_t< 768a9e65961SEric Fiselier _CheckOptionalArgsCtor<_Up>::template __enable_explicit<_Up>() 769a9e65961SEric Fiselier , int> = 0> 770a9e65961SEric Fiselier _LIBCPP_INLINE_VISIBILITY 771a9e65961SEric Fiselier constexpr explicit optional(_Up&& __v) 772a9e65961SEric Fiselier : __base(in_place, _VSTD::forward<_Up>(__v)) {} 773a9e65961SEric Fiselier 774a9e65961SEric Fiselier // LWG2756: conditionally explicit conversion from const optional<_Up>& 7754e0ea2cfSLouis Dionne template <class _Up, enable_if_t< 776a9e65961SEric Fiselier _CheckOptionalLikeCtor<_Up, _Up const&>::template __enable_implicit<_Up>() 777a9e65961SEric Fiselier , int> = 0> 778a9e65961SEric Fiselier _LIBCPP_INLINE_VISIBILITY 77954644993SChristopher Di Bella _LIBCPP_CONSTEXPR_AFTER_CXX17 optional(const optional<_Up>& __v) 780a9e65961SEric Fiselier { 781a9e65961SEric Fiselier this->__construct_from(__v); 782a9e65961SEric Fiselier } 7834e0ea2cfSLouis Dionne template <class _Up, enable_if_t< 784a9e65961SEric Fiselier _CheckOptionalLikeCtor<_Up, _Up const&>::template __enable_explicit<_Up>() 785a9e65961SEric Fiselier , int> = 0> 786a9e65961SEric Fiselier _LIBCPP_INLINE_VISIBILITY 78754644993SChristopher Di Bella _LIBCPP_CONSTEXPR_AFTER_CXX17 explicit optional(const optional<_Up>& __v) 788a9e65961SEric Fiselier { 789a9e65961SEric Fiselier this->__construct_from(__v); 790a9e65961SEric Fiselier } 791a9e65961SEric Fiselier 792a9e65961SEric Fiselier // LWG2756: conditionally explicit conversion from optional<_Up>&& 7934e0ea2cfSLouis Dionne template <class _Up, enable_if_t< 794a9e65961SEric Fiselier _CheckOptionalLikeCtor<_Up, _Up &&>::template __enable_implicit<_Up>() 795a9e65961SEric Fiselier , int> = 0> 796a9e65961SEric Fiselier _LIBCPP_INLINE_VISIBILITY 79754644993SChristopher Di Bella _LIBCPP_CONSTEXPR_AFTER_CXX17 optional(optional<_Up>&& __v) 798a9e65961SEric Fiselier { 799a9e65961SEric Fiselier this->__construct_from(_VSTD::move(__v)); 800a9e65961SEric Fiselier } 8014e0ea2cfSLouis Dionne template <class _Up, enable_if_t< 802a9e65961SEric Fiselier _CheckOptionalLikeCtor<_Up, _Up &&>::template __enable_explicit<_Up>() 803a9e65961SEric Fiselier , int> = 0> 804a9e65961SEric Fiselier _LIBCPP_INLINE_VISIBILITY 80554644993SChristopher Di Bella _LIBCPP_CONSTEXPR_AFTER_CXX17 explicit optional(optional<_Up>&& __v) 806a9e65961SEric Fiselier { 807a9e65961SEric Fiselier this->__construct_from(_VSTD::move(__v)); 808a9e65961SEric Fiselier } 809a9e65961SEric Fiselier 81017cfc57dSNikolas Klauser#if _LIBCPP_STD_VER > 20 81117cfc57dSNikolas Klauser template<class _Fp, class... _Args> 81217cfc57dSNikolas Klauser _LIBCPP_HIDE_FROM_ABI 81317cfc57dSNikolas Klauser constexpr explicit optional(__optional_construct_from_invoke_tag, _Fp&& __f, _Args&&... __args) 81417cfc57dSNikolas Klauser : __base(__optional_construct_from_invoke_tag{}, _VSTD::forward<_Fp>(__f), _VSTD::forward<_Args>(__args)...) { 81517cfc57dSNikolas Klauser } 81617cfc57dSNikolas Klauser#endif 81717cfc57dSNikolas Klauser 818a9e65961SEric Fiselier _LIBCPP_INLINE_VISIBILITY 81954644993SChristopher Di Bella _LIBCPP_CONSTEXPR_AFTER_CXX17 optional& operator=(nullopt_t) noexcept 820a9e65961SEric Fiselier { 821a9e65961SEric Fiselier reset(); 822a9e65961SEric Fiselier return *this; 823a9e65961SEric Fiselier } 824a9e65961SEric Fiselier 825a9e65961SEric Fiselier _LIBCPP_INLINE_VISIBILITY optional& operator=(const optional&) = default; 826a9e65961SEric Fiselier _LIBCPP_INLINE_VISIBILITY optional& operator=(optional&&) = default; 827a9e65961SEric Fiselier 828a9e65961SEric Fiselier // LWG2756 829a9e65961SEric Fiselier template <class _Up = value_type, 8304e0ea2cfSLouis Dionne class = enable_if_t< 8313359a17bSEric Fiselier _And< 8323359a17bSEric Fiselier _IsNotSame<__uncvref_t<_Up>, optional>, 8333359a17bSEric Fiselier _Or< 834954014a0SMarshall Clow _IsNotSame<__uncvref_t<_Up>, value_type>, 8353359a17bSEric Fiselier _Not<is_scalar<value_type>> 836015fcffdSEric Fiselier >, 837015fcffdSEric Fiselier is_constructible<value_type, _Up>, 838015fcffdSEric Fiselier is_assignable<value_type&, _Up> 839015fcffdSEric Fiselier >::value> 840a9e65961SEric Fiselier > 841a9e65961SEric Fiselier _LIBCPP_INLINE_VISIBILITY 84254644993SChristopher Di Bella _LIBCPP_CONSTEXPR_AFTER_CXX17 optional& 843a9e65961SEric Fiselier operator=(_Up&& __v) 844a9e65961SEric Fiselier { 845a9e65961SEric Fiselier if (this->has_value()) 846a9e65961SEric Fiselier this->__get() = _VSTD::forward<_Up>(__v); 847a9e65961SEric Fiselier else 848a9e65961SEric Fiselier this->__construct(_VSTD::forward<_Up>(__v)); 849a9e65961SEric Fiselier return *this; 850a9e65961SEric Fiselier } 851a9e65961SEric Fiselier 852a9e65961SEric Fiselier // LWG2756 8534e0ea2cfSLouis Dionne template <class _Up, enable_if_t< 854a9e65961SEric Fiselier _CheckOptionalLikeAssign<_Up, _Up const&>::template __enable_assign<_Up>() 855a9e65961SEric Fiselier , int> = 0> 856a9e65961SEric Fiselier _LIBCPP_INLINE_VISIBILITY 85754644993SChristopher Di Bella _LIBCPP_CONSTEXPR_AFTER_CXX17 optional& 858a9e65961SEric Fiselier operator=(const optional<_Up>& __v) 859a9e65961SEric Fiselier { 860a9e65961SEric Fiselier this->__assign_from(__v); 861a9e65961SEric Fiselier return *this; 862a9e65961SEric Fiselier } 863a9e65961SEric Fiselier 864a9e65961SEric Fiselier // LWG2756 8654e0ea2cfSLouis Dionne template <class _Up, enable_if_t< 866a9e65961SEric Fiselier _CheckOptionalLikeCtor<_Up, _Up &&>::template __enable_assign<_Up>() 867a9e65961SEric Fiselier , int> = 0> 868a9e65961SEric Fiselier _LIBCPP_INLINE_VISIBILITY 86954644993SChristopher Di Bella _LIBCPP_CONSTEXPR_AFTER_CXX17 optional& 870a9e65961SEric Fiselier operator=(optional<_Up>&& __v) 871a9e65961SEric Fiselier { 872a9e65961SEric Fiselier this->__assign_from(_VSTD::move(__v)); 873a9e65961SEric Fiselier return *this; 874a9e65961SEric Fiselier } 875a9e65961SEric Fiselier 876a9e65961SEric Fiselier template <class... _Args, 8774e0ea2cfSLouis Dionne class = enable_if_t 878a9e65961SEric Fiselier < 879a9e65961SEric Fiselier is_constructible_v<value_type, _Args...> 880a9e65961SEric Fiselier > 881a9e65961SEric Fiselier > 882a9e65961SEric Fiselier _LIBCPP_INLINE_VISIBILITY 88354644993SChristopher Di Bella _LIBCPP_CONSTEXPR_AFTER_CXX17 _Tp & 884a9e65961SEric Fiselier emplace(_Args&&... __args) 885a9e65961SEric Fiselier { 886a9e65961SEric Fiselier reset(); 887a9e65961SEric Fiselier this->__construct(_VSTD::forward<_Args>(__args)...); 8885c80f4f6SMarshall Clow return this->__get(); 889a9e65961SEric Fiselier } 890a9e65961SEric Fiselier 891a9e65961SEric Fiselier template <class _Up, class... _Args, 8924e0ea2cfSLouis Dionne class = enable_if_t 893a9e65961SEric Fiselier < 894a9e65961SEric Fiselier is_constructible_v<value_type, initializer_list<_Up>&, _Args...> 895a9e65961SEric Fiselier > 896a9e65961SEric Fiselier > 897a9e65961SEric Fiselier _LIBCPP_INLINE_VISIBILITY 89854644993SChristopher Di Bella _LIBCPP_CONSTEXPR_AFTER_CXX17 _Tp & 899a9e65961SEric Fiselier emplace(initializer_list<_Up> __il, _Args&&... __args) 900a9e65961SEric Fiselier { 901a9e65961SEric Fiselier reset(); 902a9e65961SEric Fiselier this->__construct(__il, _VSTD::forward<_Args>(__args)...); 9035c80f4f6SMarshall Clow return this->__get(); 904a9e65961SEric Fiselier } 905a9e65961SEric Fiselier 906a9e65961SEric Fiselier _LIBCPP_INLINE_VISIBILITY 90754644993SChristopher Di Bella _LIBCPP_CONSTEXPR_AFTER_CXX17 void swap(optional& __opt) 908a9e65961SEric Fiselier noexcept(is_nothrow_move_constructible_v<value_type> && 909a9e65961SEric Fiselier is_nothrow_swappable_v<value_type>) 910a9e65961SEric Fiselier { 911a9e65961SEric Fiselier if (this->has_value() == __opt.has_value()) 912a9e65961SEric Fiselier { 913a9e65961SEric Fiselier using _VSTD::swap; 914a9e65961SEric Fiselier if (this->has_value()) 915a9e65961SEric Fiselier swap(this->__get(), __opt.__get()); 916a9e65961SEric Fiselier } 917a9e65961SEric Fiselier else 918a9e65961SEric Fiselier { 919a9e65961SEric Fiselier if (this->has_value()) 920a9e65961SEric Fiselier { 921a9e65961SEric Fiselier __opt.__construct(_VSTD::move(this->__get())); 922a9e65961SEric Fiselier reset(); 923a9e65961SEric Fiselier } 924a9e65961SEric Fiselier else 925a9e65961SEric Fiselier { 926a9e65961SEric Fiselier this->__construct(_VSTD::move(__opt.__get())); 927a9e65961SEric Fiselier __opt.reset(); 928a9e65961SEric Fiselier } 929a9e65961SEric Fiselier } 930a9e65961SEric Fiselier } 931a9e65961SEric Fiselier 932a9e65961SEric Fiselier _LIBCPP_INLINE_VISIBILITY 933a9e65961SEric Fiselier constexpr 934a9e65961SEric Fiselier add_pointer_t<value_type const> 935a9e65961SEric Fiselier operator->() const 936a9e65961SEric Fiselier { 93796100f15SKristina Bessonova _LIBCPP_ASSERT(this->has_value(), "optional operator-> called on a disengaged value"); 938a9e65961SEric Fiselier return _VSTD::addressof(this->__get()); 939a9e65961SEric Fiselier } 940a9e65961SEric Fiselier 941a9e65961SEric Fiselier _LIBCPP_INLINE_VISIBILITY 942a9e65961SEric Fiselier constexpr 943a9e65961SEric Fiselier add_pointer_t<value_type> 944a9e65961SEric Fiselier operator->() 945a9e65961SEric Fiselier { 94696100f15SKristina Bessonova _LIBCPP_ASSERT(this->has_value(), "optional operator-> called on a disengaged value"); 947a9e65961SEric Fiselier return _VSTD::addressof(this->__get()); 948a9e65961SEric Fiselier } 949a9e65961SEric Fiselier 950a9e65961SEric Fiselier _LIBCPP_INLINE_VISIBILITY 951a9e65961SEric Fiselier constexpr 952a9e65961SEric Fiselier const value_type& 95300044421Szoecarver operator*() const& noexcept 954a9e65961SEric Fiselier { 95596100f15SKristina Bessonova _LIBCPP_ASSERT(this->has_value(), "optional operator* called on a disengaged value"); 956a9e65961SEric Fiselier return this->__get(); 957a9e65961SEric Fiselier } 958a9e65961SEric Fiselier 959a9e65961SEric Fiselier _LIBCPP_INLINE_VISIBILITY 960a9e65961SEric Fiselier constexpr 961a9e65961SEric Fiselier value_type& 96200044421Szoecarver operator*() & noexcept 963a9e65961SEric Fiselier { 96496100f15SKristina Bessonova _LIBCPP_ASSERT(this->has_value(), "optional operator* called on a disengaged value"); 965a9e65961SEric Fiselier return this->__get(); 966a9e65961SEric Fiselier } 967a9e65961SEric Fiselier 968a9e65961SEric Fiselier _LIBCPP_INLINE_VISIBILITY 969a9e65961SEric Fiselier constexpr 970a9e65961SEric Fiselier value_type&& 97100044421Szoecarver operator*() && noexcept 972a9e65961SEric Fiselier { 97396100f15SKristina Bessonova _LIBCPP_ASSERT(this->has_value(), "optional operator* called on a disengaged value"); 974a9e65961SEric Fiselier return _VSTD::move(this->__get()); 975a9e65961SEric Fiselier } 976a9e65961SEric Fiselier 977a9e65961SEric Fiselier _LIBCPP_INLINE_VISIBILITY 978a9e65961SEric Fiselier constexpr 979a9e65961SEric Fiselier const value_type&& 98000044421Szoecarver operator*() const&& noexcept 981a9e65961SEric Fiselier { 98296100f15SKristina Bessonova _LIBCPP_ASSERT(this->has_value(), "optional operator* called on a disengaged value"); 983a9e65961SEric Fiselier return _VSTD::move(this->__get()); 984a9e65961SEric Fiselier } 985a9e65961SEric Fiselier 986a9e65961SEric Fiselier _LIBCPP_INLINE_VISIBILITY 987a9e65961SEric Fiselier constexpr explicit operator bool() const noexcept { return has_value(); } 988a9e65961SEric Fiselier 989a9e65961SEric Fiselier using __base::has_value; 990a9e65961SEric Fiselier using __base::__get; 991a9e65961SEric Fiselier 992a9e65961SEric Fiselier _LIBCPP_INLINE_VISIBILITY 9938a063df1SLouis Dionne _LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS 994a9e65961SEric Fiselier constexpr value_type const& value() const& 995a9e65961SEric Fiselier { 996a9e65961SEric Fiselier if (!this->has_value()) 997a9e65961SEric Fiselier __throw_bad_optional_access(); 998a9e65961SEric Fiselier return this->__get(); 999a9e65961SEric Fiselier } 1000a9e65961SEric Fiselier 1001a9e65961SEric Fiselier _LIBCPP_INLINE_VISIBILITY 10028a063df1SLouis Dionne _LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS 1003a9e65961SEric Fiselier constexpr value_type& value() & 1004a9e65961SEric Fiselier { 1005a9e65961SEric Fiselier if (!this->has_value()) 1006a9e65961SEric Fiselier __throw_bad_optional_access(); 1007a9e65961SEric Fiselier return this->__get(); 1008a9e65961SEric Fiselier } 1009a9e65961SEric Fiselier 1010a9e65961SEric Fiselier _LIBCPP_INLINE_VISIBILITY 10118a063df1SLouis Dionne _LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS 1012a9e65961SEric Fiselier constexpr value_type&& value() && 1013a9e65961SEric Fiselier { 1014a9e65961SEric Fiselier if (!this->has_value()) 1015a9e65961SEric Fiselier __throw_bad_optional_access(); 1016a9e65961SEric Fiselier return _VSTD::move(this->__get()); 1017a9e65961SEric Fiselier } 1018a9e65961SEric Fiselier 1019a9e65961SEric Fiselier _LIBCPP_INLINE_VISIBILITY 10208a063df1SLouis Dionne _LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS 1021a9e65961SEric Fiselier constexpr value_type const&& value() const&& 1022a9e65961SEric Fiselier { 1023a9e65961SEric Fiselier if (!this->has_value()) 1024a9e65961SEric Fiselier __throw_bad_optional_access(); 1025a9e65961SEric Fiselier return _VSTD::move(this->__get()); 1026a9e65961SEric Fiselier } 1027a9e65961SEric Fiselier 1028a9e65961SEric Fiselier template <class _Up> 1029a9e65961SEric Fiselier _LIBCPP_INLINE_VISIBILITY 1030a9e65961SEric Fiselier constexpr value_type value_or(_Up&& __v) const& 1031a9e65961SEric Fiselier { 1032a9e65961SEric Fiselier static_assert(is_copy_constructible_v<value_type>, 1033a9e65961SEric Fiselier "optional<T>::value_or: T must be copy constructible"); 1034a9e65961SEric Fiselier static_assert(is_convertible_v<_Up, value_type>, 1035a9e65961SEric Fiselier "optional<T>::value_or: U must be convertible to T"); 1036a9e65961SEric Fiselier return this->has_value() ? this->__get() : 1037a9e65961SEric Fiselier static_cast<value_type>(_VSTD::forward<_Up>(__v)); 1038a9e65961SEric Fiselier } 1039a9e65961SEric Fiselier 1040a9e65961SEric Fiselier template <class _Up> 1041a9e65961SEric Fiselier _LIBCPP_INLINE_VISIBILITY 1042dd7c68bcSCasey Carter constexpr value_type value_or(_Up&& __v) && 1043a9e65961SEric Fiselier { 1044a9e65961SEric Fiselier static_assert(is_move_constructible_v<value_type>, 1045a9e65961SEric Fiselier "optional<T>::value_or: T must be move constructible"); 1046a9e65961SEric Fiselier static_assert(is_convertible_v<_Up, value_type>, 1047a9e65961SEric Fiselier "optional<T>::value_or: U must be convertible to T"); 1048a9e65961SEric Fiselier return this->has_value() ? _VSTD::move(this->__get()) : 1049a9e65961SEric Fiselier static_cast<value_type>(_VSTD::forward<_Up>(__v)); 1050a9e65961SEric Fiselier } 1051a9e65961SEric Fiselier 105217cfc57dSNikolas Klauser#if _LIBCPP_STD_VER > 20 105317cfc57dSNikolas Klauser template<class _Func> 1054fd4cc870SLouis Dionne _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS 105517cfc57dSNikolas Klauser constexpr auto and_then(_Func&& __f) & { 105617cfc57dSNikolas Klauser using _Up = invoke_result_t<_Func, value_type&>; 105717cfc57dSNikolas Klauser static_assert(__is_std_optional<remove_cvref_t<_Up>>::value, 105817cfc57dSNikolas Klauser "Result of f(value()) must be a specialization of std::optional"); 105917cfc57dSNikolas Klauser if (*this) 106017cfc57dSNikolas Klauser return _VSTD::invoke(_VSTD::forward<_Func>(__f), value()); 106117cfc57dSNikolas Klauser return remove_cvref_t<_Up>(); 106217cfc57dSNikolas Klauser } 106317cfc57dSNikolas Klauser 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) const& { 106717cfc57dSNikolas Klauser using _Up = invoke_result_t<_Func, const 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) && { 107817cfc57dSNikolas Klauser using _Up = invoke_result_t<_Func, value_type&&>; 107917cfc57dSNikolas Klauser static_assert(__is_std_optional<remove_cvref_t<_Up>>::value, 108017cfc57dSNikolas Klauser "Result of f(std::move(value())) must be a specialization of std::optional"); 108117cfc57dSNikolas Klauser if (*this) 108217cfc57dSNikolas Klauser return _VSTD::invoke(_VSTD::forward<_Func>(__f), _VSTD::move(value())); 108317cfc57dSNikolas Klauser return remove_cvref_t<_Up>(); 108417cfc57dSNikolas Klauser } 108517cfc57dSNikolas Klauser 108617cfc57dSNikolas Klauser template<class _Func> 108717cfc57dSNikolas Klauser _LIBCPP_HIDE_FROM_ABI 108817cfc57dSNikolas Klauser constexpr auto and_then(_Func&& __f) const&& { 108917cfc57dSNikolas Klauser using _Up = invoke_result_t<_Func, const 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> 1098fd4cc870SLouis Dionne _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS 109917cfc57dSNikolas Klauser constexpr auto transform(_Func&& __f) & { 110017cfc57dSNikolas Klauser using _Up = remove_cv_t<invoke_result_t<_Func, value_type&>>; 110117cfc57dSNikolas Klauser static_assert(!is_array_v<_Up>, "Result of f(value()) should not be an Array"); 110217cfc57dSNikolas Klauser static_assert(!is_same_v<_Up, in_place_t>, 110317cfc57dSNikolas Klauser "Result of f(value()) should not be std::in_place_t"); 110417cfc57dSNikolas Klauser static_assert(!is_same_v<_Up, nullopt_t>, 110517cfc57dSNikolas Klauser "Result of f(value()) should not be std::nullopt_t"); 110617cfc57dSNikolas Klauser static_assert(is_object_v<_Up>, "Result of f(value()) should be an object type"); 110717cfc57dSNikolas Klauser if (*this) 110817cfc57dSNikolas Klauser return optional<_Up>(__optional_construct_from_invoke_tag{}, _VSTD::forward<_Func>(__f), value()); 110917cfc57dSNikolas Klauser return optional<_Up>(); 111017cfc57dSNikolas Klauser } 111117cfc57dSNikolas Klauser 111217cfc57dSNikolas Klauser template<class _Func> 1113fd4cc870SLouis Dionne _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS 111417cfc57dSNikolas Klauser constexpr auto transform(_Func&& __f) const& { 111517cfc57dSNikolas Klauser using _Up = remove_cv_t<invoke_result_t<_Func, const value_type&>>; 111617cfc57dSNikolas Klauser static_assert(!is_array_v<_Up>, "Result of f(value()) should not be an Array"); 111717cfc57dSNikolas Klauser static_assert(!is_same_v<_Up, in_place_t>, 111817cfc57dSNikolas Klauser "Result of f(value()) should not be std::in_place_t"); 111917cfc57dSNikolas Klauser static_assert(!is_same_v<_Up, nullopt_t>, 112017cfc57dSNikolas Klauser "Result of f(value()) should not be std::nullopt_t"); 112117cfc57dSNikolas Klauser static_assert(is_object_v<_Up>, "Result of f(value()) should be an object type"); 112217cfc57dSNikolas Klauser if (*this) 112317cfc57dSNikolas Klauser return optional<_Up>(__optional_construct_from_invoke_tag{}, _VSTD::forward<_Func>(__f), value()); 112417cfc57dSNikolas Klauser return optional<_Up>(); 112517cfc57dSNikolas Klauser } 112617cfc57dSNikolas Klauser 112717cfc57dSNikolas Klauser template<class _Func> 1128fd4cc870SLouis Dionne _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS 112917cfc57dSNikolas Klauser constexpr auto transform(_Func&& __f) && { 113017cfc57dSNikolas Klauser using _Up = remove_cv_t<invoke_result_t<_Func, value_type&&>>; 113117cfc57dSNikolas Klauser static_assert(!is_array_v<_Up>, "Result of f(std::move(value())) should not be an Array"); 113217cfc57dSNikolas Klauser static_assert(!is_same_v<_Up, in_place_t>, 113317cfc57dSNikolas Klauser "Result of f(std::move(value())) should not be std::in_place_t"); 113417cfc57dSNikolas Klauser static_assert(!is_same_v<_Up, nullopt_t>, 113517cfc57dSNikolas Klauser "Result of f(std::move(value())) should not be std::nullopt_t"); 113617cfc57dSNikolas Klauser static_assert(is_object_v<_Up>, "Result of f(std::move(value())) should be an object type"); 113717cfc57dSNikolas Klauser if (*this) 113817cfc57dSNikolas Klauser return optional<_Up>(__optional_construct_from_invoke_tag{}, _VSTD::forward<_Func>(__f), _VSTD::move(value())); 113917cfc57dSNikolas Klauser return optional<_Up>(); 114017cfc57dSNikolas Klauser } 114117cfc57dSNikolas Klauser 114217cfc57dSNikolas Klauser template<class _Func> 1143fd4cc870SLouis Dionne _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS 114417cfc57dSNikolas Klauser constexpr auto transform(_Func&& __f) const&& { 114517cfc57dSNikolas Klauser using _Up = remove_cvref_t<invoke_result_t<_Func, const value_type&&>>; 114617cfc57dSNikolas Klauser static_assert(!is_array_v<_Up>, "Result of f(std::move(value())) should not be an Array"); 114717cfc57dSNikolas Klauser static_assert(!is_same_v<_Up, in_place_t>, 114817cfc57dSNikolas Klauser "Result of f(std::move(value())) should not be std::in_place_t"); 114917cfc57dSNikolas Klauser static_assert(!is_same_v<_Up, nullopt_t>, 115017cfc57dSNikolas Klauser "Result of f(std::move(value())) should not be std::nullopt_t"); 115117cfc57dSNikolas Klauser static_assert(is_object_v<_Up>, "Result of f(std::move(value())) should be an object type"); 115217cfc57dSNikolas Klauser if (*this) 115317cfc57dSNikolas Klauser return optional<_Up>(__optional_construct_from_invoke_tag{}, _VSTD::forward<_Func>(__f), _VSTD::move(value())); 115417cfc57dSNikolas Klauser return optional<_Up>(); 115517cfc57dSNikolas Klauser } 115617cfc57dSNikolas Klauser 115717cfc57dSNikolas Klauser template<invocable _Func> 115817cfc57dSNikolas Klauser _LIBCPP_HIDE_FROM_ABI 115917cfc57dSNikolas Klauser constexpr optional or_else(_Func&& __f) const& requires is_copy_constructible_v<value_type> { 116017cfc57dSNikolas Klauser static_assert(is_same_v<remove_cvref_t<invoke_result_t<_Func>>, optional>, 116117cfc57dSNikolas Klauser "Result of f() should be the same type as this optional"); 116217cfc57dSNikolas Klauser if (*this) 116317cfc57dSNikolas Klauser return *this; 116417cfc57dSNikolas Klauser return _VSTD::forward<_Func>(__f)(); 116517cfc57dSNikolas Klauser } 116617cfc57dSNikolas Klauser 116717cfc57dSNikolas Klauser template<invocable _Func> 116817cfc57dSNikolas Klauser _LIBCPP_HIDE_FROM_ABI 116917cfc57dSNikolas Klauser constexpr optional or_else(_Func&& __f) && requires is_move_constructible_v<value_type> { 117017cfc57dSNikolas Klauser static_assert(is_same_v<remove_cvref_t<invoke_result_t<_Func>>, optional>, 117117cfc57dSNikolas Klauser "Result of f() should be the same type as this optional"); 117217cfc57dSNikolas Klauser if (*this) 117317cfc57dSNikolas Klauser return _VSTD::move(*this); 117417cfc57dSNikolas Klauser return _VSTD::forward<_Func>(__f)(); 117517cfc57dSNikolas Klauser } 117617cfc57dSNikolas Klauser#endif // _LIBCPP_STD_VER > 20 117717cfc57dSNikolas Klauser 1178a9e65961SEric Fiselier using __base::reset; 1179a9e65961SEric Fiselier}; 1180a9e65961SEric Fiselier 118101666904SLouis Dionne#if _LIBCPP_STD_VER >= 17 1182a8f1a715SArthur O'Dwyertemplate<class _Tp> 1183a8f1a715SArthur O'Dwyer optional(_Tp) -> optional<_Tp>; 1184f35b4bc3SMarshall Clow#endif 1185f35b4bc3SMarshall Clow 1186a9e65961SEric Fiselier// Comparisons between optionals 1187dc808af3SEric Fiseliertemplate <class _Tp, class _Up> 1188a9e65961SEric Fiselier_LIBCPP_INLINE_VISIBILITY constexpr 11894e0ea2cfSLouis Dionneenable_if_t< 1190ab3fcc50SArthur O'Dwyer is_convertible_v<decltype(declval<const _Tp&>() == 1191ab3fcc50SArthur O'Dwyer declval<const _Up&>()), bool>, 1192a9e65961SEric Fiselier bool 1193a9e65961SEric Fiselier> 1194dc808af3SEric Fiselieroperator==(const optional<_Tp>& __x, const optional<_Up>& __y) 1195a9e65961SEric Fiselier{ 1196a9e65961SEric Fiselier if (static_cast<bool>(__x) != static_cast<bool>(__y)) 1197a9e65961SEric Fiselier return false; 1198a9e65961SEric Fiselier if (!static_cast<bool>(__x)) 1199a9e65961SEric Fiselier return true; 1200a9e65961SEric Fiselier return *__x == *__y; 1201a9e65961SEric Fiselier} 1202a9e65961SEric Fiselier 1203dc808af3SEric Fiseliertemplate <class _Tp, class _Up> 1204a9e65961SEric Fiselier_LIBCPP_INLINE_VISIBILITY constexpr 12054e0ea2cfSLouis Dionneenable_if_t< 1206ab3fcc50SArthur O'Dwyer is_convertible_v<decltype(declval<const _Tp&>() != 1207ab3fcc50SArthur O'Dwyer declval<const _Up&>()), bool>, 1208a9e65961SEric Fiselier bool 1209a9e65961SEric Fiselier> 1210dc808af3SEric Fiselieroperator!=(const optional<_Tp>& __x, const optional<_Up>& __y) 1211a9e65961SEric Fiselier{ 1212a9e65961SEric Fiselier if (static_cast<bool>(__x) != static_cast<bool>(__y)) 1213a9e65961SEric Fiselier return true; 1214a9e65961SEric Fiselier if (!static_cast<bool>(__x)) 1215a9e65961SEric Fiselier return false; 1216a9e65961SEric Fiselier return *__x != *__y; 1217a9e65961SEric Fiselier} 1218a9e65961SEric Fiselier 1219dc808af3SEric Fiseliertemplate <class _Tp, class _Up> 1220a9e65961SEric Fiselier_LIBCPP_INLINE_VISIBILITY constexpr 12214e0ea2cfSLouis Dionneenable_if_t< 1222ab3fcc50SArthur O'Dwyer is_convertible_v<decltype(declval<const _Tp&>() < 1223ab3fcc50SArthur O'Dwyer declval<const _Up&>()), bool>, 1224a9e65961SEric Fiselier bool 1225a9e65961SEric Fiselier> 1226dc808af3SEric Fiselieroperator<(const optional<_Tp>& __x, const optional<_Up>& __y) 1227a9e65961SEric Fiselier{ 1228a9e65961SEric Fiselier if (!static_cast<bool>(__y)) 1229a9e65961SEric Fiselier return false; 1230a9e65961SEric Fiselier if (!static_cast<bool>(__x)) 1231a9e65961SEric Fiselier return true; 1232a9e65961SEric Fiselier return *__x < *__y; 1233a9e65961SEric Fiselier} 1234a9e65961SEric Fiselier 1235dc808af3SEric Fiseliertemplate <class _Tp, class _Up> 1236a9e65961SEric Fiselier_LIBCPP_INLINE_VISIBILITY constexpr 12374e0ea2cfSLouis Dionneenable_if_t< 1238ab3fcc50SArthur O'Dwyer is_convertible_v<decltype(declval<const _Tp&>() > 1239ab3fcc50SArthur O'Dwyer declval<const _Up&>()), bool>, 1240a9e65961SEric Fiselier bool 1241a9e65961SEric Fiselier> 1242dc808af3SEric Fiselieroperator>(const optional<_Tp>& __x, const optional<_Up>& __y) 1243a9e65961SEric Fiselier{ 1244a9e65961SEric Fiselier if (!static_cast<bool>(__x)) 1245a9e65961SEric Fiselier return false; 1246a9e65961SEric Fiselier if (!static_cast<bool>(__y)) 1247a9e65961SEric Fiselier return true; 1248a9e65961SEric Fiselier return *__x > *__y; 1249a9e65961SEric Fiselier} 1250a9e65961SEric Fiselier 1251dc808af3SEric Fiseliertemplate <class _Tp, class _Up> 1252a9e65961SEric Fiselier_LIBCPP_INLINE_VISIBILITY constexpr 12534e0ea2cfSLouis Dionneenable_if_t< 1254ab3fcc50SArthur O'Dwyer is_convertible_v<decltype(declval<const _Tp&>() <= 1255ab3fcc50SArthur O'Dwyer declval<const _Up&>()), bool>, 1256a9e65961SEric Fiselier bool 1257a9e65961SEric Fiselier> 1258dc808af3SEric Fiselieroperator<=(const optional<_Tp>& __x, const optional<_Up>& __y) 1259a9e65961SEric Fiselier{ 1260a9e65961SEric Fiselier if (!static_cast<bool>(__x)) 1261a9e65961SEric Fiselier return true; 1262a9e65961SEric Fiselier if (!static_cast<bool>(__y)) 1263a9e65961SEric Fiselier return false; 1264a9e65961SEric Fiselier return *__x <= *__y; 1265a9e65961SEric Fiselier} 1266a9e65961SEric Fiselier 1267dc808af3SEric Fiseliertemplate <class _Tp, class _Up> 1268a9e65961SEric Fiselier_LIBCPP_INLINE_VISIBILITY constexpr 12694e0ea2cfSLouis Dionneenable_if_t< 1270ab3fcc50SArthur O'Dwyer is_convertible_v<decltype(declval<const _Tp&>() >= 1271ab3fcc50SArthur O'Dwyer declval<const _Up&>()), bool>, 1272a9e65961SEric Fiselier bool 1273a9e65961SEric Fiselier> 1274dc808af3SEric Fiselieroperator>=(const optional<_Tp>& __x, const optional<_Up>& __y) 1275a9e65961SEric Fiselier{ 1276a9e65961SEric Fiselier if (!static_cast<bool>(__y)) 1277a9e65961SEric Fiselier return true; 1278a9e65961SEric Fiselier if (!static_cast<bool>(__x)) 1279a9e65961SEric Fiselier return false; 1280a9e65961SEric Fiselier return *__x >= *__y; 1281a9e65961SEric Fiselier} 1282a9e65961SEric Fiselier 1283a9e65961SEric Fiselier// Comparisons with nullopt 1284a9e65961SEric Fiseliertemplate <class _Tp> 1285a9e65961SEric Fiselier_LIBCPP_INLINE_VISIBILITY constexpr 1286a9e65961SEric Fiselierbool 1287a9e65961SEric Fiselieroperator==(const optional<_Tp>& __x, nullopt_t) noexcept 1288a9e65961SEric Fiselier{ 1289a9e65961SEric Fiselier return !static_cast<bool>(__x); 1290a9e65961SEric Fiselier} 1291a9e65961SEric Fiselier 1292a9e65961SEric Fiseliertemplate <class _Tp> 1293a9e65961SEric Fiselier_LIBCPP_INLINE_VISIBILITY constexpr 1294a9e65961SEric Fiselierbool 1295a9e65961SEric Fiselieroperator==(nullopt_t, const optional<_Tp>& __x) noexcept 1296a9e65961SEric Fiselier{ 1297a9e65961SEric Fiselier return !static_cast<bool>(__x); 1298a9e65961SEric Fiselier} 1299a9e65961SEric Fiselier 1300a9e65961SEric Fiseliertemplate <class _Tp> 1301a9e65961SEric Fiselier_LIBCPP_INLINE_VISIBILITY constexpr 1302a9e65961SEric Fiselierbool 1303a9e65961SEric Fiselieroperator!=(const optional<_Tp>& __x, nullopt_t) noexcept 1304a9e65961SEric Fiselier{ 1305a9e65961SEric Fiselier return static_cast<bool>(__x); 1306a9e65961SEric Fiselier} 1307a9e65961SEric Fiselier 1308a9e65961SEric Fiseliertemplate <class _Tp> 1309a9e65961SEric Fiselier_LIBCPP_INLINE_VISIBILITY constexpr 1310a9e65961SEric Fiselierbool 1311a9e65961SEric Fiselieroperator!=(nullopt_t, const optional<_Tp>& __x) noexcept 1312a9e65961SEric Fiselier{ 1313a9e65961SEric Fiselier return static_cast<bool>(__x); 1314a9e65961SEric Fiselier} 1315a9e65961SEric Fiselier 1316a9e65961SEric Fiseliertemplate <class _Tp> 1317a9e65961SEric Fiselier_LIBCPP_INLINE_VISIBILITY constexpr 1318a9e65961SEric Fiselierbool 1319a9e65961SEric Fiselieroperator<(const optional<_Tp>&, nullopt_t) noexcept 1320a9e65961SEric Fiselier{ 1321a9e65961SEric Fiselier return false; 1322a9e65961SEric Fiselier} 1323a9e65961SEric Fiselier 1324a9e65961SEric Fiseliertemplate <class _Tp> 1325a9e65961SEric Fiselier_LIBCPP_INLINE_VISIBILITY constexpr 1326a9e65961SEric Fiselierbool 1327a9e65961SEric Fiselieroperator<(nullopt_t, const optional<_Tp>& __x) noexcept 1328a9e65961SEric Fiselier{ 1329a9e65961SEric Fiselier return static_cast<bool>(__x); 1330a9e65961SEric Fiselier} 1331a9e65961SEric Fiselier 1332a9e65961SEric Fiseliertemplate <class _Tp> 1333a9e65961SEric Fiselier_LIBCPP_INLINE_VISIBILITY constexpr 1334a9e65961SEric Fiselierbool 1335a9e65961SEric Fiselieroperator<=(const optional<_Tp>& __x, nullopt_t) noexcept 1336a9e65961SEric Fiselier{ 1337a9e65961SEric Fiselier return !static_cast<bool>(__x); 1338a9e65961SEric Fiselier} 1339a9e65961SEric Fiselier 1340a9e65961SEric Fiseliertemplate <class _Tp> 1341a9e65961SEric Fiselier_LIBCPP_INLINE_VISIBILITY constexpr 1342a9e65961SEric Fiselierbool 1343fd838227SEric Fiselieroperator<=(nullopt_t, const optional<_Tp>&) noexcept 1344a9e65961SEric Fiselier{ 1345a9e65961SEric Fiselier return true; 1346a9e65961SEric Fiselier} 1347a9e65961SEric Fiselier 1348a9e65961SEric Fiseliertemplate <class _Tp> 1349a9e65961SEric Fiselier_LIBCPP_INLINE_VISIBILITY constexpr 1350a9e65961SEric Fiselierbool 1351a9e65961SEric Fiselieroperator>(const optional<_Tp>& __x, nullopt_t) noexcept 1352a9e65961SEric Fiselier{ 1353a9e65961SEric Fiselier return static_cast<bool>(__x); 1354a9e65961SEric Fiselier} 1355a9e65961SEric Fiselier 1356a9e65961SEric Fiseliertemplate <class _Tp> 1357a9e65961SEric Fiselier_LIBCPP_INLINE_VISIBILITY constexpr 1358a9e65961SEric Fiselierbool 1359fd838227SEric Fiselieroperator>(nullopt_t, const optional<_Tp>&) noexcept 1360a9e65961SEric Fiselier{ 1361a9e65961SEric Fiselier return false; 1362a9e65961SEric Fiselier} 1363a9e65961SEric Fiselier 1364a9e65961SEric Fiseliertemplate <class _Tp> 1365a9e65961SEric Fiselier_LIBCPP_INLINE_VISIBILITY constexpr 1366a9e65961SEric Fiselierbool 1367a9e65961SEric Fiselieroperator>=(const optional<_Tp>&, nullopt_t) noexcept 1368a9e65961SEric Fiselier{ 1369a9e65961SEric Fiselier return true; 1370a9e65961SEric Fiselier} 1371a9e65961SEric Fiselier 1372a9e65961SEric Fiseliertemplate <class _Tp> 1373a9e65961SEric Fiselier_LIBCPP_INLINE_VISIBILITY constexpr 1374a9e65961SEric Fiselierbool 1375a9e65961SEric Fiselieroperator>=(nullopt_t, const optional<_Tp>& __x) noexcept 1376a9e65961SEric Fiselier{ 1377a9e65961SEric Fiselier return !static_cast<bool>(__x); 1378a9e65961SEric Fiselier} 1379a9e65961SEric Fiselier 1380a9e65961SEric Fiselier// Comparisons with T 1381dc808af3SEric Fiseliertemplate <class _Tp, class _Up> 1382a9e65961SEric Fiselier_LIBCPP_INLINE_VISIBILITY constexpr 13834e0ea2cfSLouis Dionneenable_if_t< 1384ab3fcc50SArthur O'Dwyer is_convertible_v<decltype(declval<const _Tp&>() == 1385ab3fcc50SArthur O'Dwyer declval<const _Up&>()), bool>, 1386a9e65961SEric Fiselier bool 1387a9e65961SEric Fiselier> 1388dc808af3SEric Fiselieroperator==(const optional<_Tp>& __x, const _Up& __v) 1389a9e65961SEric Fiselier{ 1390a9e65961SEric Fiselier return static_cast<bool>(__x) ? *__x == __v : false; 1391a9e65961SEric Fiselier} 1392a9e65961SEric Fiselier 1393dc808af3SEric Fiseliertemplate <class _Tp, class _Up> 1394a9e65961SEric Fiselier_LIBCPP_INLINE_VISIBILITY constexpr 13954e0ea2cfSLouis Dionneenable_if_t< 1396ab3fcc50SArthur O'Dwyer is_convertible_v<decltype(declval<const _Tp&>() == 1397ab3fcc50SArthur O'Dwyer declval<const _Up&>()), bool>, 1398a9e65961SEric Fiselier bool 1399a9e65961SEric Fiselier> 1400dc808af3SEric Fiselieroperator==(const _Tp& __v, const optional<_Up>& __x) 1401a9e65961SEric Fiselier{ 1402a9e65961SEric Fiselier return static_cast<bool>(__x) ? __v == *__x : false; 1403a9e65961SEric Fiselier} 1404a9e65961SEric Fiselier 1405dc808af3SEric Fiseliertemplate <class _Tp, class _Up> 1406a9e65961SEric Fiselier_LIBCPP_INLINE_VISIBILITY constexpr 14074e0ea2cfSLouis Dionneenable_if_t< 1408ab3fcc50SArthur O'Dwyer is_convertible_v<decltype(declval<const _Tp&>() != 1409ab3fcc50SArthur O'Dwyer declval<const _Up&>()), bool>, 1410a9e65961SEric Fiselier bool 1411a9e65961SEric Fiselier> 1412dc808af3SEric Fiselieroperator!=(const optional<_Tp>& __x, const _Up& __v) 1413a9e65961SEric Fiselier{ 1414a9e65961SEric Fiselier return static_cast<bool>(__x) ? *__x != __v : true; 1415a9e65961SEric Fiselier} 1416a9e65961SEric Fiselier 1417dc808af3SEric Fiseliertemplate <class _Tp, class _Up> 1418a9e65961SEric Fiselier_LIBCPP_INLINE_VISIBILITY constexpr 14194e0ea2cfSLouis Dionneenable_if_t< 1420ab3fcc50SArthur O'Dwyer is_convertible_v<decltype(declval<const _Tp&>() != 1421ab3fcc50SArthur O'Dwyer declval<const _Up&>()), bool>, 1422a9e65961SEric Fiselier bool 1423a9e65961SEric Fiselier> 1424dc808af3SEric Fiselieroperator!=(const _Tp& __v, const optional<_Up>& __x) 1425a9e65961SEric Fiselier{ 1426a9e65961SEric Fiselier return static_cast<bool>(__x) ? __v != *__x : true; 1427a9e65961SEric Fiselier} 1428a9e65961SEric Fiselier 1429dc808af3SEric Fiseliertemplate <class _Tp, class _Up> 1430a9e65961SEric Fiselier_LIBCPP_INLINE_VISIBILITY constexpr 14314e0ea2cfSLouis Dionneenable_if_t< 1432ab3fcc50SArthur O'Dwyer is_convertible_v<decltype(declval<const _Tp&>() < 1433ab3fcc50SArthur O'Dwyer declval<const _Up&>()), bool>, 1434a9e65961SEric Fiselier bool 1435a9e65961SEric Fiselier> 1436dc808af3SEric Fiselieroperator<(const optional<_Tp>& __x, const _Up& __v) 1437a9e65961SEric Fiselier{ 1438a9e65961SEric Fiselier return static_cast<bool>(__x) ? *__x < __v : true; 1439a9e65961SEric Fiselier} 1440a9e65961SEric Fiselier 1441dc808af3SEric Fiseliertemplate <class _Tp, class _Up> 1442a9e65961SEric Fiselier_LIBCPP_INLINE_VISIBILITY constexpr 14434e0ea2cfSLouis Dionneenable_if_t< 1444ab3fcc50SArthur O'Dwyer is_convertible_v<decltype(declval<const _Tp&>() < 1445ab3fcc50SArthur O'Dwyer declval<const _Up&>()), bool>, 1446a9e65961SEric Fiselier bool 1447a9e65961SEric Fiselier> 1448dc808af3SEric Fiselieroperator<(const _Tp& __v, const optional<_Up>& __x) 1449a9e65961SEric Fiselier{ 1450a9e65961SEric Fiselier return static_cast<bool>(__x) ? __v < *__x : false; 1451a9e65961SEric Fiselier} 1452a9e65961SEric Fiselier 1453dc808af3SEric Fiseliertemplate <class _Tp, class _Up> 1454a9e65961SEric Fiselier_LIBCPP_INLINE_VISIBILITY constexpr 14554e0ea2cfSLouis Dionneenable_if_t< 1456ab3fcc50SArthur O'Dwyer is_convertible_v<decltype(declval<const _Tp&>() <= 1457ab3fcc50SArthur O'Dwyer declval<const _Up&>()), bool>, 1458a9e65961SEric Fiselier bool 1459a9e65961SEric Fiselier> 1460dc808af3SEric Fiselieroperator<=(const optional<_Tp>& __x, const _Up& __v) 1461a9e65961SEric Fiselier{ 1462a9e65961SEric Fiselier return static_cast<bool>(__x) ? *__x <= __v : true; 1463a9e65961SEric Fiselier} 1464a9e65961SEric Fiselier 1465dc808af3SEric Fiseliertemplate <class _Tp, class _Up> 1466a9e65961SEric Fiselier_LIBCPP_INLINE_VISIBILITY constexpr 14674e0ea2cfSLouis Dionneenable_if_t< 1468ab3fcc50SArthur O'Dwyer is_convertible_v<decltype(declval<const _Tp&>() <= 1469ab3fcc50SArthur O'Dwyer declval<const _Up&>()), bool>, 1470a9e65961SEric Fiselier bool 1471a9e65961SEric Fiselier> 1472dc808af3SEric Fiselieroperator<=(const _Tp& __v, const optional<_Up>& __x) 1473a9e65961SEric Fiselier{ 1474a9e65961SEric Fiselier return static_cast<bool>(__x) ? __v <= *__x : false; 1475a9e65961SEric Fiselier} 1476a9e65961SEric Fiselier 1477dc808af3SEric Fiseliertemplate <class _Tp, class _Up> 1478a9e65961SEric Fiselier_LIBCPP_INLINE_VISIBILITY constexpr 14794e0ea2cfSLouis Dionneenable_if_t< 1480ab3fcc50SArthur O'Dwyer is_convertible_v<decltype(declval<const _Tp&>() > 1481ab3fcc50SArthur O'Dwyer declval<const _Up&>()), bool>, 1482a9e65961SEric Fiselier bool 1483a9e65961SEric Fiselier> 1484dc808af3SEric Fiselieroperator>(const optional<_Tp>& __x, const _Up& __v) 1485a9e65961SEric Fiselier{ 1486a9e65961SEric Fiselier return static_cast<bool>(__x) ? *__x > __v : false; 1487a9e65961SEric Fiselier} 1488a9e65961SEric Fiselier 1489dc808af3SEric Fiseliertemplate <class _Tp, class _Up> 1490a9e65961SEric Fiselier_LIBCPP_INLINE_VISIBILITY constexpr 14914e0ea2cfSLouis Dionneenable_if_t< 1492ab3fcc50SArthur O'Dwyer is_convertible_v<decltype(declval<const _Tp&>() > 1493ab3fcc50SArthur O'Dwyer declval<const _Up&>()), bool>, 1494a9e65961SEric Fiselier bool 1495a9e65961SEric Fiselier> 1496dc808af3SEric Fiselieroperator>(const _Tp& __v, const optional<_Up>& __x) 1497a9e65961SEric Fiselier{ 1498a9e65961SEric Fiselier return static_cast<bool>(__x) ? __v > *__x : true; 1499a9e65961SEric Fiselier} 1500a9e65961SEric Fiselier 1501dc808af3SEric Fiseliertemplate <class _Tp, class _Up> 1502a9e65961SEric Fiselier_LIBCPP_INLINE_VISIBILITY constexpr 15034e0ea2cfSLouis Dionneenable_if_t< 1504ab3fcc50SArthur O'Dwyer is_convertible_v<decltype(declval<const _Tp&>() >= 1505ab3fcc50SArthur O'Dwyer declval<const _Up&>()), bool>, 1506a9e65961SEric Fiselier bool 1507a9e65961SEric Fiselier> 1508dc808af3SEric Fiselieroperator>=(const optional<_Tp>& __x, const _Up& __v) 1509a9e65961SEric Fiselier{ 1510a9e65961SEric Fiselier return static_cast<bool>(__x) ? *__x >= __v : false; 1511a9e65961SEric Fiselier} 1512a9e65961SEric Fiselier 1513dc808af3SEric Fiseliertemplate <class _Tp, class _Up> 1514a9e65961SEric Fiselier_LIBCPP_INLINE_VISIBILITY constexpr 15154e0ea2cfSLouis Dionneenable_if_t< 1516ab3fcc50SArthur O'Dwyer is_convertible_v<decltype(declval<const _Tp&>() >= 1517ab3fcc50SArthur O'Dwyer declval<const _Up&>()), bool>, 1518a9e65961SEric Fiselier bool 1519a9e65961SEric Fiselier> 1520dc808af3SEric Fiselieroperator>=(const _Tp& __v, const optional<_Up>& __x) 1521a9e65961SEric Fiselier{ 1522a9e65961SEric Fiselier return static_cast<bool>(__x) ? __v >= *__x : true; 1523a9e65961SEric Fiselier} 1524a9e65961SEric Fiselier 1525a9e65961SEric Fiselier 1526a9e65961SEric Fiseliertemplate <class _Tp> 152754644993SChristopher Di Bellainline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 15284e0ea2cfSLouis Dionneenable_if_t< 1529a9e65961SEric Fiselier is_move_constructible_v<_Tp> && is_swappable_v<_Tp>, 1530a9e65961SEric Fiselier void 1531a9e65961SEric Fiselier> 1532a9e65961SEric Fiselierswap(optional<_Tp>& __x, optional<_Tp>& __y) noexcept(noexcept(__x.swap(__y))) 1533a9e65961SEric Fiselier{ 1534a9e65961SEric Fiselier __x.swap(__y); 1535a9e65961SEric Fiselier} 1536a9e65961SEric Fiselier 1537a9e65961SEric Fiseliertemplate <class _Tp> 1538a9e65961SEric Fiselier_LIBCPP_INLINE_VISIBILITY constexpr 1539a9e65961SEric Fiselieroptional<decay_t<_Tp>> make_optional(_Tp&& __v) 1540a9e65961SEric Fiselier{ 1541a9e65961SEric Fiselier return optional<decay_t<_Tp>>(_VSTD::forward<_Tp>(__v)); 1542a9e65961SEric Fiselier} 1543a9e65961SEric Fiselier 1544a9e65961SEric Fiseliertemplate <class _Tp, class... _Args> 1545a9e65961SEric Fiselier_LIBCPP_INLINE_VISIBILITY constexpr 1546a9e65961SEric Fiselieroptional<_Tp> make_optional(_Args&&... __args) 1547a9e65961SEric Fiselier{ 1548a9e65961SEric Fiselier return optional<_Tp>(in_place, _VSTD::forward<_Args>(__args)...); 1549a9e65961SEric Fiselier} 1550a9e65961SEric Fiselier 1551a9e65961SEric Fiseliertemplate <class _Tp, class _Up, class... _Args> 1552a9e65961SEric Fiselier_LIBCPP_INLINE_VISIBILITY constexpr 1553a9e65961SEric Fiselieroptional<_Tp> make_optional(initializer_list<_Up> __il, _Args&&... __args) 1554a9e65961SEric Fiselier{ 1555a9e65961SEric Fiselier return optional<_Tp>(in_place, __il, _VSTD::forward<_Args>(__args)...); 1556a9e65961SEric Fiselier} 1557a9e65961SEric Fiselier 1558a9e65961SEric Fiseliertemplate <class _Tp> 1559f9127593SEric Fiselierstruct _LIBCPP_TEMPLATE_VIS hash< 1560f9127593SEric Fiselier __enable_hash_helper<optional<_Tp>, remove_const_t<_Tp>> 1561f9127593SEric Fiselier> 1562a9e65961SEric Fiselier{ 1563dc066888SArthur O'Dwyer#if _LIBCPP_STD_VER <= 17 || defined(_LIBCPP_ENABLE_CXX20_REMOVED_BINDER_TYPEDEFS) 1564dc066888SArthur O'Dwyer _LIBCPP_DEPRECATED_IN_CXX17 typedef optional<_Tp> argument_type; 1565dc066888SArthur O'Dwyer _LIBCPP_DEPRECATED_IN_CXX17 typedef size_t result_type; 1566dc066888SArthur O'Dwyer#endif 1567a9e65961SEric Fiselier 1568a9e65961SEric Fiselier _LIBCPP_INLINE_VISIBILITY 1569dc066888SArthur O'Dwyer size_t operator()(const optional<_Tp>& __opt) const 1570a9e65961SEric Fiselier { 1571f9127593SEric Fiselier return static_cast<bool>(__opt) ? hash<remove_const_t<_Tp>>()(*__opt) : 0; 1572a9e65961SEric Fiselier } 1573a9e65961SEric Fiselier}; 1574a9e65961SEric Fiselier 1575a9e65961SEric Fiselier_LIBCPP_END_NAMESPACE_STD 1576a9e65961SEric Fiselier 1577a9e65961SEric Fiselier#endif // _LIBCPP_STD_VER > 14 1578a9e65961SEric Fiselier 1579a9e65961SEric Fiselier#endif // _LIBCPP_OPTIONAL 1580