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 1612eadbc86SLouis Dionne#include <__availability> 16217cfc57dSNikolas Klauser#include <__concepts/invocable.h> 163bfbd73f8SArthur O'Dwyer#include <__config> 164a9e65961SEric Fiselier#include <__debug> 1652d0f1fa4SArthur O'Dwyer#include <compare> 166a9e65961SEric Fiselier#include <functional> 167a9e65961SEric Fiselier#include <initializer_list> 168a9e65961SEric Fiselier#include <new> 169a9e65961SEric Fiselier#include <stdexcept> 170a9e65961SEric Fiselier#include <type_traits> 171a9e65961SEric Fiselier#include <utility> 172f56972e2SMarshall Clow#include <version> 173a9e65961SEric Fiselier 174*169a66eaSNikolas Klauser// TODO: remove these headers 175*169a66eaSNikolas Klauser#include <__memory/allocator_arg_t.h> 176*169a66eaSNikolas Klauser#include <__memory/uses_allocator.h> 177*169a66eaSNikolas Klauser#include <typeinfo> 178*169a66eaSNikolas Klauser 179a9e65961SEric Fiselier#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 180a9e65961SEric Fiselier# pragma GCC system_header 181a9e65961SEric Fiselier#endif 182a9e65961SEric Fiselier 183a9e65961SEric Fiseliernamespace std // purposefully not using versioning namespace 184a9e65961SEric Fiselier{ 185a9e65961SEric Fiselier 1868a063df1SLouis Dionneclass _LIBCPP_EXCEPTION_ABI _LIBCPP_AVAILABILITY_BAD_OPTIONAL_ACCESS bad_optional_access 187e29b1ed5SMarshall Clow : public exception 188a9e65961SEric Fiselier{ 189a9e65961SEric Fiselierpublic: 190a9e65961SEric Fiselier // Get the key function ~bad_optional_access() into the dylib 1916a1d0785SMarshall Clow virtual ~bad_optional_access() _NOEXCEPT; 192e29b1ed5SMarshall Clow virtual const char* what() const _NOEXCEPT; 193a9e65961SEric Fiselier}; 194a9e65961SEric Fiselier 195d2b0df35SNikolas Klauser} // namespace std 196a9e65961SEric Fiselier 197a9e65961SEric Fiselier#if _LIBCPP_STD_VER > 14 198a9e65961SEric Fiselier 199a9e65961SEric Fiselier_LIBCPP_BEGIN_NAMESPACE_STD 200a9e65961SEric Fiselier 201a9e65961SEric Fiselier_LIBCPP_NORETURN 202a9e65961SEric Fiselierinline _LIBCPP_INLINE_VISIBILITY 2038a063df1SLouis Dionne_LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS 204a9e65961SEric Fiseliervoid __throw_bad_optional_access() { 205a9e65961SEric Fiselier#ifndef _LIBCPP_NO_EXCEPTIONS 206a9e65961SEric Fiselier throw bad_optional_access(); 207a9e65961SEric Fiselier#else 208a9e65961SEric Fiselier _VSTD::abort(); 209a9e65961SEric Fiselier#endif 210a9e65961SEric Fiselier} 211a9e65961SEric Fiselier 212a9e65961SEric Fiselierstruct nullopt_t 213a9e65961SEric Fiselier{ 214a9e65961SEric Fiselier struct __secret_tag { _LIBCPP_INLINE_VISIBILITY explicit __secret_tag() = default; }; 215a9e65961SEric Fiselier _LIBCPP_INLINE_VISIBILITY constexpr explicit nullopt_t(__secret_tag, __secret_tag) noexcept {} 216a9e65961SEric Fiselier}; 217a9e65961SEric Fiselier 218cb793e1aSLouis Dionneinline constexpr nullopt_t nullopt{nullopt_t::__secret_tag{}, nullopt_t::__secret_tag{}}; 219a9e65961SEric Fiselier 22017cfc57dSNikolas Klauserstruct __optional_construct_from_invoke_tag {}; 22117cfc57dSNikolas Klauser 222a9e65961SEric Fiseliertemplate <class _Tp, bool = is_trivially_destructible<_Tp>::value> 223a9e65961SEric Fiselierstruct __optional_destruct_base; 224a9e65961SEric Fiselier 225a9e65961SEric Fiseliertemplate <class _Tp> 226a9e65961SEric Fiselierstruct __optional_destruct_base<_Tp, false> 227a9e65961SEric Fiselier{ 228a9e65961SEric Fiselier typedef _Tp value_type; 229a9e65961SEric Fiselier static_assert(is_object_v<value_type>, 230a9e65961SEric Fiselier "instantiation of optional with a non-object type is undefined behavior"); 231a9e65961SEric Fiselier union 232a9e65961SEric Fiselier { 233a9e65961SEric Fiselier char __null_state_; 234a9e65961SEric Fiselier value_type __val_; 235a9e65961SEric Fiselier }; 236a9e65961SEric Fiselier bool __engaged_; 237a9e65961SEric Fiselier 238a9e65961SEric Fiselier _LIBCPP_INLINE_VISIBILITY 23954644993SChristopher Di Bella _LIBCPP_CONSTEXPR_AFTER_CXX17 ~__optional_destruct_base() 240a9e65961SEric Fiselier { 241a9e65961SEric Fiselier if (__engaged_) 242a9e65961SEric Fiselier __val_.~value_type(); 243a9e65961SEric Fiselier } 244a9e65961SEric Fiselier 245a9e65961SEric Fiselier _LIBCPP_INLINE_VISIBILITY 246a9e65961SEric Fiselier constexpr __optional_destruct_base() noexcept 247a9e65961SEric Fiselier : __null_state_(), 248a9e65961SEric Fiselier __engaged_(false) {} 249a9e65961SEric Fiselier 250a9e65961SEric Fiselier template <class... _Args> 251a9e65961SEric Fiselier _LIBCPP_INLINE_VISIBILITY 252a9e65961SEric Fiselier constexpr explicit __optional_destruct_base(in_place_t, _Args&&... __args) 253a9e65961SEric Fiselier : __val_(_VSTD::forward<_Args>(__args)...), 254a9e65961SEric Fiselier __engaged_(true) {} 255a9e65961SEric Fiselier 25617cfc57dSNikolas Klauser#if _LIBCPP_STD_VER > 20 25717cfc57dSNikolas Klauser template <class _Fp, class... _Args> 25817cfc57dSNikolas Klauser _LIBCPP_HIDE_FROM_ABI 25917cfc57dSNikolas Klauser constexpr __optional_destruct_base(__optional_construct_from_invoke_tag, _Fp&& __f, _Args&&... __args) 26017cfc57dSNikolas Klauser : __val_(_VSTD::invoke(_VSTD::forward<_Fp>(__f), _VSTD::forward<_Args>(__args)...)), __engaged_(true) {} 26117cfc57dSNikolas Klauser#endif 26217cfc57dSNikolas Klauser 263a9e65961SEric Fiselier _LIBCPP_INLINE_VISIBILITY 26454644993SChristopher Di Bella _LIBCPP_CONSTEXPR_AFTER_CXX17 void reset() noexcept 265a9e65961SEric Fiselier { 266a9e65961SEric Fiselier if (__engaged_) 267a9e65961SEric Fiselier { 268a9e65961SEric Fiselier __val_.~value_type(); 269a9e65961SEric Fiselier __engaged_ = false; 270a9e65961SEric Fiselier } 271a9e65961SEric Fiselier } 272a9e65961SEric Fiselier}; 273a9e65961SEric Fiselier 274a9e65961SEric Fiseliertemplate <class _Tp> 275a9e65961SEric Fiselierstruct __optional_destruct_base<_Tp, true> 276a9e65961SEric Fiselier{ 277a9e65961SEric Fiselier typedef _Tp value_type; 278a9e65961SEric Fiselier static_assert(is_object_v<value_type>, 279a9e65961SEric Fiselier "instantiation of optional with a non-object type is undefined behavior"); 280a9e65961SEric Fiselier union 281a9e65961SEric Fiselier { 282a9e65961SEric Fiselier char __null_state_; 283a9e65961SEric Fiselier value_type __val_; 284a9e65961SEric Fiselier }; 285a9e65961SEric Fiselier bool __engaged_; 286a9e65961SEric Fiselier 287a9e65961SEric Fiselier _LIBCPP_INLINE_VISIBILITY 288a9e65961SEric Fiselier constexpr __optional_destruct_base() noexcept 289a9e65961SEric Fiselier : __null_state_(), 290a9e65961SEric Fiselier __engaged_(false) {} 291a9e65961SEric Fiselier 292a9e65961SEric Fiselier template <class... _Args> 293a9e65961SEric Fiselier _LIBCPP_INLINE_VISIBILITY 294a9e65961SEric Fiselier constexpr explicit __optional_destruct_base(in_place_t, _Args&&... __args) 295a9e65961SEric Fiselier : __val_(_VSTD::forward<_Args>(__args)...), 296a9e65961SEric Fiselier __engaged_(true) {} 297a9e65961SEric Fiselier 29817cfc57dSNikolas Klauser#if _LIBCPP_STD_VER > 20 29917cfc57dSNikolas Klauser template <class _Fp, class... _Args> 30017cfc57dSNikolas Klauser _LIBCPP_HIDE_FROM_ABI 30117cfc57dSNikolas Klauser constexpr __optional_destruct_base(__optional_construct_from_invoke_tag, _Fp&& __f, _Args&&... __args) 30217cfc57dSNikolas Klauser : __val_(_VSTD::invoke(_VSTD::forward<_Fp>(__f), _VSTD::forward<_Args>(__args)...)), __engaged_(true) {} 30317cfc57dSNikolas Klauser#endif 30417cfc57dSNikolas Klauser 305a9e65961SEric Fiselier _LIBCPP_INLINE_VISIBILITY 30654644993SChristopher Di Bella _LIBCPP_CONSTEXPR_AFTER_CXX17 void reset() noexcept 307a9e65961SEric Fiselier { 308a9e65961SEric Fiselier if (__engaged_) 309a9e65961SEric Fiselier { 310a9e65961SEric Fiselier __engaged_ = false; 311a9e65961SEric Fiselier } 312a9e65961SEric Fiselier } 313a9e65961SEric Fiselier}; 314a9e65961SEric Fiselier 315a9e65961SEric Fiseliertemplate <class _Tp, bool = is_reference<_Tp>::value> 316a9e65961SEric Fiselierstruct __optional_storage_base : __optional_destruct_base<_Tp> 317a9e65961SEric Fiselier{ 318a9e65961SEric Fiselier using __base = __optional_destruct_base<_Tp>; 319a9e65961SEric Fiselier using value_type = _Tp; 320a9e65961SEric Fiselier using __base::__base; 321a9e65961SEric Fiselier 322a9e65961SEric Fiselier _LIBCPP_INLINE_VISIBILITY 323a9e65961SEric Fiselier constexpr bool has_value() const noexcept 324a9e65961SEric Fiselier { 325a9e65961SEric Fiselier return this->__engaged_; 326a9e65961SEric Fiselier } 327a9e65961SEric Fiselier 328a9e65961SEric Fiselier _LIBCPP_INLINE_VISIBILITY 329a9e65961SEric Fiselier constexpr value_type& __get() & noexcept 330a9e65961SEric Fiselier { 331a9e65961SEric Fiselier return this->__val_; 332a9e65961SEric Fiselier } 333a9e65961SEric Fiselier _LIBCPP_INLINE_VISIBILITY 334a9e65961SEric Fiselier constexpr const value_type& __get() const& noexcept 335a9e65961SEric Fiselier { 336a9e65961SEric Fiselier return this->__val_; 337a9e65961SEric Fiselier } 338a9e65961SEric Fiselier _LIBCPP_INLINE_VISIBILITY 339a9e65961SEric Fiselier constexpr value_type&& __get() && noexcept 340a9e65961SEric Fiselier { 341a9e65961SEric Fiselier return _VSTD::move(this->__val_); 342a9e65961SEric Fiselier } 343a9e65961SEric Fiselier _LIBCPP_INLINE_VISIBILITY 344a9e65961SEric Fiselier constexpr const value_type&& __get() const&& noexcept 345a9e65961SEric Fiselier { 346a9e65961SEric Fiselier return _VSTD::move(this->__val_); 347a9e65961SEric Fiselier } 348a9e65961SEric Fiselier 349a9e65961SEric Fiselier template <class... _Args> 350a9e65961SEric Fiselier _LIBCPP_INLINE_VISIBILITY 35154644993SChristopher Di Bella _LIBCPP_CONSTEXPR_AFTER_CXX17 void __construct(_Args&&... __args) 352a9e65961SEric Fiselier { 353a9e65961SEric Fiselier _LIBCPP_ASSERT(!has_value(), "__construct called for engaged __optional_storage"); 35454644993SChristopher Di Bella#if _LIBCPP_STD_VER > 17 35554644993SChristopher Di Bella _VSTD::construct_at(_VSTD::addressof(this->__val_), _VSTD::forward<_Args>(__args)...); 35654644993SChristopher Di Bella#else 357a9e65961SEric Fiselier ::new ((void*)_VSTD::addressof(this->__val_)) value_type(_VSTD::forward<_Args>(__args)...); 35854644993SChristopher Di Bella#endif 359a9e65961SEric Fiselier this->__engaged_ = true; 360a9e65961SEric Fiselier } 361a9e65961SEric Fiselier 362a9e65961SEric Fiselier template <class _That> 363a9e65961SEric Fiselier _LIBCPP_INLINE_VISIBILITY 36454644993SChristopher Di Bella _LIBCPP_CONSTEXPR_AFTER_CXX17 void __construct_from(_That&& __opt) 365a9e65961SEric Fiselier { 366a9e65961SEric Fiselier if (__opt.has_value()) 367a9e65961SEric Fiselier __construct(_VSTD::forward<_That>(__opt).__get()); 368a9e65961SEric Fiselier } 369a9e65961SEric Fiselier 370a9e65961SEric Fiselier template <class _That> 371a9e65961SEric Fiselier _LIBCPP_INLINE_VISIBILITY 37254644993SChristopher Di Bella _LIBCPP_CONSTEXPR_AFTER_CXX17 void __assign_from(_That&& __opt) 373a9e65961SEric Fiselier { 374a9e65961SEric Fiselier if (this->__engaged_ == __opt.has_value()) 375a9e65961SEric Fiselier { 376a9e65961SEric Fiselier if (this->__engaged_) 377a9e65961SEric Fiselier this->__val_ = _VSTD::forward<_That>(__opt).__get(); 378a9e65961SEric Fiselier } 379a9e65961SEric Fiselier else 380a9e65961SEric Fiselier { 381a9e65961SEric Fiselier if (this->__engaged_) 382a9e65961SEric Fiselier this->reset(); 383a9e65961SEric Fiselier else 384a9e65961SEric Fiselier __construct(_VSTD::forward<_That>(__opt).__get()); 385a9e65961SEric Fiselier } 386a9e65961SEric Fiselier } 387a9e65961SEric Fiselier}; 388a9e65961SEric Fiselier 389a9e65961SEric Fiselier// optional<T&> is currently required ill-formed, however it may to be in the 390a9e65961SEric Fiselier// future. For this reason it has already been implemented to ensure we can 391a9e65961SEric Fiselier// make the change in an ABI compatible manner. 392a9e65961SEric Fiseliertemplate <class _Tp> 393a9e65961SEric Fiselierstruct __optional_storage_base<_Tp, true> 394a9e65961SEric Fiselier{ 395a9e65961SEric Fiselier using value_type = _Tp; 396a9e65961SEric Fiselier using __raw_type = remove_reference_t<_Tp>; 397a9e65961SEric Fiselier __raw_type* __value_; 398a9e65961SEric Fiselier 399a9e65961SEric Fiselier template <class _Up> 400a9e65961SEric Fiselier static constexpr bool __can_bind_reference() { 401a9e65961SEric Fiselier using _RawUp = typename remove_reference<_Up>::type; 402a9e65961SEric Fiselier using _UpPtr = _RawUp*; 403a9e65961SEric Fiselier using _RawTp = typename remove_reference<_Tp>::type; 404a9e65961SEric Fiselier using _TpPtr = _RawTp*; 405a9e65961SEric Fiselier using _CheckLValueArg = integral_constant<bool, 406a9e65961SEric Fiselier (is_lvalue_reference<_Up>::value && is_convertible<_UpPtr, _TpPtr>::value) 407a9e65961SEric Fiselier || is_same<_RawUp, reference_wrapper<_RawTp>>::value 408a9e65961SEric Fiselier || is_same<_RawUp, reference_wrapper<typename remove_const<_RawTp>::type>>::value 409a9e65961SEric Fiselier >; 410a9e65961SEric Fiselier return (is_lvalue_reference<_Tp>::value && _CheckLValueArg::value) 411a9e65961SEric Fiselier || (is_rvalue_reference<_Tp>::value && !is_lvalue_reference<_Up>::value && 412a9e65961SEric Fiselier is_convertible<_UpPtr, _TpPtr>::value); 413a9e65961SEric Fiselier } 414a9e65961SEric Fiselier 415a9e65961SEric Fiselier _LIBCPP_INLINE_VISIBILITY 416a9e65961SEric Fiselier constexpr __optional_storage_base() noexcept 417a9e65961SEric Fiselier : __value_(nullptr) {} 418a9e65961SEric Fiselier 419a9e65961SEric Fiselier template <class _UArg> 420a9e65961SEric Fiselier _LIBCPP_INLINE_VISIBILITY 421a9e65961SEric Fiselier constexpr explicit __optional_storage_base(in_place_t, _UArg&& __uarg) 422a9e65961SEric Fiselier : __value_(_VSTD::addressof(__uarg)) 423a9e65961SEric Fiselier { 424a9e65961SEric Fiselier static_assert(__can_bind_reference<_UArg>(), 425a9e65961SEric Fiselier "Attempted to construct a reference element in tuple from a " 426a9e65961SEric Fiselier "possible temporary"); 427a9e65961SEric Fiselier } 428a9e65961SEric Fiselier 429a9e65961SEric Fiselier _LIBCPP_INLINE_VISIBILITY 43054644993SChristopher Di Bella _LIBCPP_CONSTEXPR_AFTER_CXX17 void reset() noexcept { __value_ = nullptr; } 431a9e65961SEric Fiselier 432a9e65961SEric Fiselier _LIBCPP_INLINE_VISIBILITY 433a9e65961SEric Fiselier constexpr bool has_value() const noexcept 434a9e65961SEric Fiselier { return __value_ != nullptr; } 435a9e65961SEric Fiselier 436a9e65961SEric Fiselier _LIBCPP_INLINE_VISIBILITY 437a9e65961SEric Fiselier constexpr value_type& __get() const& noexcept 438a9e65961SEric Fiselier { return *__value_; } 439a9e65961SEric Fiselier 440a9e65961SEric Fiselier _LIBCPP_INLINE_VISIBILITY 441a9e65961SEric Fiselier constexpr value_type&& __get() const&& noexcept 442a9e65961SEric Fiselier { return _VSTD::forward<value_type>(*__value_); } 443a9e65961SEric Fiselier 444a9e65961SEric Fiselier template <class _UArg> 445a9e65961SEric Fiselier _LIBCPP_INLINE_VISIBILITY 44654644993SChristopher Di Bella _LIBCPP_CONSTEXPR_AFTER_CXX17 void __construct(_UArg&& __val) 447a9e65961SEric Fiselier { 448a9e65961SEric Fiselier _LIBCPP_ASSERT(!has_value(), "__construct called for engaged __optional_storage"); 449a9e65961SEric Fiselier static_assert(__can_bind_reference<_UArg>(), 450a9e65961SEric Fiselier "Attempted to construct a reference element in tuple from a " 451a9e65961SEric Fiselier "possible temporary"); 452a9e65961SEric Fiselier __value_ = _VSTD::addressof(__val); 453a9e65961SEric Fiselier } 454a9e65961SEric Fiselier 455a9e65961SEric Fiselier template <class _That> 456a9e65961SEric Fiselier _LIBCPP_INLINE_VISIBILITY 45754644993SChristopher Di Bella _LIBCPP_CONSTEXPR_AFTER_CXX17 void __construct_from(_That&& __opt) 458a9e65961SEric Fiselier { 459a9e65961SEric Fiselier if (__opt.has_value()) 460a9e65961SEric Fiselier __construct(_VSTD::forward<_That>(__opt).__get()); 461a9e65961SEric Fiselier } 462a9e65961SEric Fiselier 463a9e65961SEric Fiselier template <class _That> 464a9e65961SEric Fiselier _LIBCPP_INLINE_VISIBILITY 46554644993SChristopher Di Bella _LIBCPP_CONSTEXPR_AFTER_CXX17 void __assign_from(_That&& __opt) 466a9e65961SEric Fiselier { 467a9e65961SEric Fiselier if (has_value() == __opt.has_value()) 468a9e65961SEric Fiselier { 469a9e65961SEric Fiselier if (has_value()) 470a9e65961SEric Fiselier *__value_ = _VSTD::forward<_That>(__opt).__get(); 471a9e65961SEric Fiselier } 472a9e65961SEric Fiselier else 473a9e65961SEric Fiselier { 474a9e65961SEric Fiselier if (has_value()) 475a9e65961SEric Fiselier reset(); 476a9e65961SEric Fiselier else 477a9e65961SEric Fiselier __construct(_VSTD::forward<_That>(__opt).__get()); 478a9e65961SEric Fiselier } 479a9e65961SEric Fiselier } 480a9e65961SEric Fiselier}; 481a9e65961SEric Fiselier 482f2d571c8SCasey Cartertemplate <class _Tp, bool = is_trivially_copy_constructible<_Tp>::value> 483f2d571c8SCasey Carterstruct __optional_copy_base : __optional_storage_base<_Tp> 484a9e65961SEric Fiselier{ 485a9e65961SEric Fiselier using __optional_storage_base<_Tp>::__optional_storage_base; 486a9e65961SEric Fiselier}; 487a9e65961SEric Fiselier 488a9e65961SEric Fiseliertemplate <class _Tp> 489f2d571c8SCasey Carterstruct __optional_copy_base<_Tp, false> : __optional_storage_base<_Tp> 490a9e65961SEric Fiselier{ 491a9e65961SEric Fiselier using __optional_storage_base<_Tp>::__optional_storage_base; 492a9e65961SEric Fiselier 493a9e65961SEric Fiselier _LIBCPP_INLINE_VISIBILITY 494f2d571c8SCasey Carter __optional_copy_base() = default; 495a9e65961SEric Fiselier 496a9e65961SEric Fiselier _LIBCPP_INLINE_VISIBILITY 49754644993SChristopher Di Bella _LIBCPP_CONSTEXPR_AFTER_CXX17 __optional_copy_base(const __optional_copy_base& __opt) 498a9e65961SEric Fiselier { 499a9e65961SEric Fiselier this->__construct_from(__opt); 500a9e65961SEric Fiselier } 501a9e65961SEric Fiselier 502a9e65961SEric Fiselier _LIBCPP_INLINE_VISIBILITY 503f2d571c8SCasey Carter __optional_copy_base(__optional_copy_base&&) = default; 504f2d571c8SCasey Carter _LIBCPP_INLINE_VISIBILITY 505f2d571c8SCasey Carter __optional_copy_base& operator=(const __optional_copy_base&) = default; 506f2d571c8SCasey Carter _LIBCPP_INLINE_VISIBILITY 507f2d571c8SCasey Carter __optional_copy_base& operator=(__optional_copy_base&&) = default; 508f2d571c8SCasey Carter}; 509f2d571c8SCasey Carter 510f2d571c8SCasey Cartertemplate <class _Tp, bool = is_trivially_move_constructible<_Tp>::value> 511f2d571c8SCasey Carterstruct __optional_move_base : __optional_copy_base<_Tp> 512f2d571c8SCasey Carter{ 513f2d571c8SCasey Carter using __optional_copy_base<_Tp>::__optional_copy_base; 514f2d571c8SCasey Carter}; 515f2d571c8SCasey Carter 516f2d571c8SCasey Cartertemplate <class _Tp> 517f2d571c8SCasey Carterstruct __optional_move_base<_Tp, false> : __optional_copy_base<_Tp> 518f2d571c8SCasey Carter{ 519f2d571c8SCasey Carter using value_type = _Tp; 520f2d571c8SCasey Carter using __optional_copy_base<_Tp>::__optional_copy_base; 521f2d571c8SCasey Carter 522f2d571c8SCasey Carter _LIBCPP_INLINE_VISIBILITY 523f2d571c8SCasey Carter __optional_move_base() = default; 524f2d571c8SCasey Carter _LIBCPP_INLINE_VISIBILITY 525f2d571c8SCasey Carter __optional_move_base(const __optional_move_base&) = default; 526f2d571c8SCasey Carter 527f2d571c8SCasey Carter _LIBCPP_INLINE_VISIBILITY 52854644993SChristopher Di Bella _LIBCPP_CONSTEXPR_AFTER_CXX17 __optional_move_base(__optional_move_base&& __opt) 529a9e65961SEric Fiselier noexcept(is_nothrow_move_constructible_v<value_type>) 530a9e65961SEric Fiselier { 531a9e65961SEric Fiselier this->__construct_from(_VSTD::move(__opt)); 532a9e65961SEric Fiselier } 533a9e65961SEric Fiselier 534a9e65961SEric Fiselier _LIBCPP_INLINE_VISIBILITY 535f2d571c8SCasey Carter __optional_move_base& operator=(const __optional_move_base&) = default; 536f2d571c8SCasey Carter _LIBCPP_INLINE_VISIBILITY 537f2d571c8SCasey Carter __optional_move_base& operator=(__optional_move_base&&) = default; 538f2d571c8SCasey Carter}; 539f2d571c8SCasey Carter 540f2d571c8SCasey Cartertemplate <class _Tp, bool = 541f2d571c8SCasey Carter is_trivially_destructible<_Tp>::value && 542f2d571c8SCasey Carter is_trivially_copy_constructible<_Tp>::value && 543f2d571c8SCasey Carter is_trivially_copy_assignable<_Tp>::value> 544f2d571c8SCasey Carterstruct __optional_copy_assign_base : __optional_move_base<_Tp> 545f2d571c8SCasey Carter{ 546f2d571c8SCasey Carter using __optional_move_base<_Tp>::__optional_move_base; 547f2d571c8SCasey Carter}; 548f2d571c8SCasey Carter 549f2d571c8SCasey Cartertemplate <class _Tp> 550f2d571c8SCasey Carterstruct __optional_copy_assign_base<_Tp, false> : __optional_move_base<_Tp> 551f2d571c8SCasey Carter{ 552f2d571c8SCasey Carter using __optional_move_base<_Tp>::__optional_move_base; 553f2d571c8SCasey Carter 554f2d571c8SCasey Carter _LIBCPP_INLINE_VISIBILITY 555f2d571c8SCasey Carter __optional_copy_assign_base() = default; 556f2d571c8SCasey Carter _LIBCPP_INLINE_VISIBILITY 557f2d571c8SCasey Carter __optional_copy_assign_base(const __optional_copy_assign_base&) = default; 558f2d571c8SCasey Carter _LIBCPP_INLINE_VISIBILITY 559f2d571c8SCasey Carter __optional_copy_assign_base(__optional_copy_assign_base&&) = default; 560f2d571c8SCasey Carter 561f2d571c8SCasey Carter _LIBCPP_INLINE_VISIBILITY 56254644993SChristopher Di Bella _LIBCPP_CONSTEXPR_AFTER_CXX17 __optional_copy_assign_base& operator=(const __optional_copy_assign_base& __opt) 563a9e65961SEric Fiselier { 564a9e65961SEric Fiselier this->__assign_from(__opt); 565a9e65961SEric Fiselier return *this; 566a9e65961SEric Fiselier } 567a9e65961SEric Fiselier 568a9e65961SEric Fiselier _LIBCPP_INLINE_VISIBILITY 569f2d571c8SCasey Carter __optional_copy_assign_base& operator=(__optional_copy_assign_base&&) = default; 570f2d571c8SCasey Carter}; 571f2d571c8SCasey Carter 572f2d571c8SCasey Cartertemplate <class _Tp, bool = 573f2d571c8SCasey Carter is_trivially_destructible<_Tp>::value && 574f2d571c8SCasey Carter is_trivially_move_constructible<_Tp>::value && 575f2d571c8SCasey Carter is_trivially_move_assignable<_Tp>::value> 576f2d571c8SCasey Carterstruct __optional_move_assign_base : __optional_copy_assign_base<_Tp> 577f2d571c8SCasey Carter{ 578f2d571c8SCasey Carter using __optional_copy_assign_base<_Tp>::__optional_copy_assign_base; 579f2d571c8SCasey Carter}; 580f2d571c8SCasey Carter 581f2d571c8SCasey Cartertemplate <class _Tp> 582f2d571c8SCasey Carterstruct __optional_move_assign_base<_Tp, false> : __optional_copy_assign_base<_Tp> 583f2d571c8SCasey Carter{ 584f2d571c8SCasey Carter using value_type = _Tp; 585f2d571c8SCasey Carter using __optional_copy_assign_base<_Tp>::__optional_copy_assign_base; 586f2d571c8SCasey Carter 587f2d571c8SCasey Carter _LIBCPP_INLINE_VISIBILITY 588f2d571c8SCasey Carter __optional_move_assign_base() = default; 589f2d571c8SCasey Carter _LIBCPP_INLINE_VISIBILITY 590f2d571c8SCasey Carter __optional_move_assign_base(const __optional_move_assign_base& __opt) = default; 591f2d571c8SCasey Carter _LIBCPP_INLINE_VISIBILITY 592f2d571c8SCasey Carter __optional_move_assign_base(__optional_move_assign_base&&) = default; 593f2d571c8SCasey Carter _LIBCPP_INLINE_VISIBILITY 594f2d571c8SCasey Carter __optional_move_assign_base& operator=(const __optional_move_assign_base&) = default; 595f2d571c8SCasey Carter 596f2d571c8SCasey Carter _LIBCPP_INLINE_VISIBILITY 59754644993SChristopher Di Bella _LIBCPP_CONSTEXPR_AFTER_CXX17 __optional_move_assign_base& operator=(__optional_move_assign_base&& __opt) 598a9e65961SEric Fiselier noexcept(is_nothrow_move_assignable_v<value_type> && 599a9e65961SEric Fiselier is_nothrow_move_constructible_v<value_type>) 600a9e65961SEric Fiselier { 601a9e65961SEric Fiselier this->__assign_from(_VSTD::move(__opt)); 602a9e65961SEric Fiselier return *this; 603a9e65961SEric Fiselier } 604a9e65961SEric Fiselier}; 605a9e65961SEric Fiselier 606a9e65961SEric Fiseliertemplate <class _Tp> 607a9e65961SEric Fiselierusing __optional_sfinae_ctor_base_t = __sfinae_ctor_base< 608a9e65961SEric Fiselier is_copy_constructible<_Tp>::value, 609a9e65961SEric Fiselier is_move_constructible<_Tp>::value 610a9e65961SEric Fiselier>; 611a9e65961SEric Fiselier 612a9e65961SEric Fiseliertemplate <class _Tp> 613a9e65961SEric Fiselierusing __optional_sfinae_assign_base_t = __sfinae_assign_base< 614a9e65961SEric Fiselier (is_copy_constructible<_Tp>::value && is_copy_assignable<_Tp>::value), 615a9e65961SEric Fiselier (is_move_constructible<_Tp>::value && is_move_assignable<_Tp>::value) 616a9e65961SEric Fiselier>; 617a9e65961SEric Fiselier 618a9e65961SEric Fiseliertemplate<class _Tp> 61917cfc57dSNikolas Klauserclass optional; 62017cfc57dSNikolas Klausertemplate <class _Tp> 62117cfc57dSNikolas Klauserstruct __is_std_optional : false_type {}; 62217cfc57dSNikolas Klausertemplate <class _Tp> struct __is_std_optional<optional<_Tp>> : true_type {}; 62317cfc57dSNikolas Klauser 62417cfc57dSNikolas Klausertemplate <class _Tp> 625a9e65961SEric Fiselierclass optional 626f2d571c8SCasey Carter : private __optional_move_assign_base<_Tp> 627a9e65961SEric Fiselier , private __optional_sfinae_ctor_base_t<_Tp> 628a9e65961SEric Fiselier , private __optional_sfinae_assign_base_t<_Tp> 629a9e65961SEric Fiselier{ 630f2d571c8SCasey Carter using __base = __optional_move_assign_base<_Tp>; 631a9e65961SEric Fiselierpublic: 632a9e65961SEric Fiselier using value_type = _Tp; 633a9e65961SEric Fiselier 634a9e65961SEric Fiselierprivate: 635a9e65961SEric Fiselier // Disable the reference extension using this static assert. 63636db4898SMarshall Clow static_assert(!is_same_v<__uncvref_t<value_type>, in_place_t>, 637a9e65961SEric Fiselier "instantiation of optional with in_place_t is ill-formed"); 638a9e65961SEric Fiselier static_assert(!is_same_v<__uncvref_t<value_type>, nullopt_t>, 639a9e65961SEric Fiselier "instantiation of optional with nullopt_t is ill-formed"); 640a9e65961SEric Fiselier static_assert(!is_reference_v<value_type>, 641a9e65961SEric Fiselier "instantiation of optional with a reference type is ill-formed"); 642a9e65961SEric Fiselier static_assert(is_destructible_v<value_type>, 643a9e65961SEric Fiselier "instantiation of optional with a non-destructible type is ill-formed"); 64436db4898SMarshall Clow static_assert(!is_array_v<value_type>, 64536db4898SMarshall Clow "instantiation of optional with an array type is ill-formed"); 646a9e65961SEric Fiselier 647a9e65961SEric Fiselier // LWG2756: conditionally explicit conversion from _Up 648a9e65961SEric Fiselier struct _CheckOptionalArgsConstructor { 649a9e65961SEric Fiselier template <class _Up> 650a9e65961SEric Fiselier static constexpr bool __enable_implicit() { 651a9e65961SEric Fiselier return is_constructible_v<_Tp, _Up&&> && 652a9e65961SEric Fiselier is_convertible_v<_Up&&, _Tp>; 653a9e65961SEric Fiselier } 654a9e65961SEric Fiselier 655a9e65961SEric Fiselier template <class _Up> 656a9e65961SEric Fiselier static constexpr bool __enable_explicit() { 657a9e65961SEric Fiselier return is_constructible_v<_Tp, _Up&&> && 658a9e65961SEric Fiselier !is_convertible_v<_Up&&, _Tp>; 659a9e65961SEric Fiselier } 660a9e65961SEric Fiselier }; 661a9e65961SEric Fiselier template <class _Up> 6623359a17bSEric Fiselier using _CheckOptionalArgsCtor = _If< 6633359a17bSEric Fiselier _IsNotSame<__uncvref_t<_Up>, in_place_t>::value && 6643359a17bSEric Fiselier _IsNotSame<__uncvref_t<_Up>, optional>::value, 665a9e65961SEric Fiselier _CheckOptionalArgsConstructor, 666a9e65961SEric Fiselier __check_tuple_constructor_fail 667a9e65961SEric Fiselier >; 668a9e65961SEric Fiselier template <class _QualUp> 669a9e65961SEric Fiselier struct _CheckOptionalLikeConstructor { 670a9e65961SEric Fiselier template <class _Up, class _Opt = optional<_Up>> 6713359a17bSEric Fiselier using __check_constructible_from_opt = _Or< 672a9e65961SEric Fiselier is_constructible<_Tp, _Opt&>, 673a9e65961SEric Fiselier is_constructible<_Tp, _Opt const&>, 674a9e65961SEric Fiselier is_constructible<_Tp, _Opt&&>, 675a9e65961SEric Fiselier is_constructible<_Tp, _Opt const&&>, 676a9e65961SEric Fiselier is_convertible<_Opt&, _Tp>, 677a9e65961SEric Fiselier is_convertible<_Opt const&, _Tp>, 678a9e65961SEric Fiselier is_convertible<_Opt&&, _Tp>, 679a9e65961SEric Fiselier is_convertible<_Opt const&&, _Tp> 680a9e65961SEric Fiselier >; 681a9e65961SEric Fiselier template <class _Up, class _Opt = optional<_Up>> 6823359a17bSEric Fiselier using __check_assignable_from_opt = _Or< 683a9e65961SEric Fiselier is_assignable<_Tp&, _Opt&>, 684a9e65961SEric Fiselier is_assignable<_Tp&, _Opt const&>, 685a9e65961SEric Fiselier is_assignable<_Tp&, _Opt&&>, 686a9e65961SEric Fiselier is_assignable<_Tp&, _Opt const&&> 687a9e65961SEric Fiselier >; 688a9e65961SEric Fiselier template <class _Up, class _QUp = _QualUp> 689a9e65961SEric Fiselier static constexpr bool __enable_implicit() { 690a9e65961SEric Fiselier return is_convertible<_QUp, _Tp>::value && 691a9e65961SEric Fiselier !__check_constructible_from_opt<_Up>::value; 692a9e65961SEric Fiselier } 693a9e65961SEric Fiselier template <class _Up, class _QUp = _QualUp> 694a9e65961SEric Fiselier static constexpr bool __enable_explicit() { 695a9e65961SEric Fiselier return !is_convertible<_QUp, _Tp>::value && 696a9e65961SEric Fiselier !__check_constructible_from_opt<_Up>::value; 697a9e65961SEric Fiselier } 698a9e65961SEric Fiselier template <class _Up, class _QUp = _QualUp> 699a9e65961SEric Fiselier static constexpr bool __enable_assign() { 700b6f19174SArthur O'Dwyer // Construction and assignability of _QUp to _Tp has already been 701a9e65961SEric Fiselier // checked. 702a9e65961SEric Fiselier return !__check_constructible_from_opt<_Up>::value && 703a9e65961SEric Fiselier !__check_assignable_from_opt<_Up>::value; 704a9e65961SEric Fiselier } 705a9e65961SEric Fiselier }; 706a9e65961SEric Fiselier 707a9e65961SEric Fiselier template <class _Up, class _QualUp> 7083359a17bSEric Fiselier using _CheckOptionalLikeCtor = _If< 7093359a17bSEric Fiselier _And< 7103359a17bSEric Fiselier _IsNotSame<_Up, _Tp>, 711a9e65961SEric Fiselier is_constructible<_Tp, _QualUp> 712a9e65961SEric Fiselier >::value, 713a9e65961SEric Fiselier _CheckOptionalLikeConstructor<_QualUp>, 714a9e65961SEric Fiselier __check_tuple_constructor_fail 715a9e65961SEric Fiselier >; 716a9e65961SEric Fiselier template <class _Up, class _QualUp> 7173359a17bSEric Fiselier using _CheckOptionalLikeAssign = _If< 7183359a17bSEric Fiselier _And< 7193359a17bSEric Fiselier _IsNotSame<_Up, _Tp>, 720a9e65961SEric Fiselier is_constructible<_Tp, _QualUp>, 721a9e65961SEric Fiselier is_assignable<_Tp&, _QualUp> 722a9e65961SEric Fiselier >::value, 723a9e65961SEric Fiselier _CheckOptionalLikeConstructor<_QualUp>, 724a9e65961SEric Fiselier __check_tuple_constructor_fail 725a9e65961SEric Fiselier >; 72617cfc57dSNikolas Klauser 727a9e65961SEric Fiselierpublic: 728a9e65961SEric Fiselier 729a9e65961SEric Fiselier _LIBCPP_INLINE_VISIBILITY constexpr optional() noexcept {} 730c1bcd4c1SMarshall Clow _LIBCPP_INLINE_VISIBILITY constexpr optional(const optional&) = default; 731c1bcd4c1SMarshall Clow _LIBCPP_INLINE_VISIBILITY constexpr optional(optional&&) = default; 732a9e65961SEric Fiselier _LIBCPP_INLINE_VISIBILITY constexpr optional(nullopt_t) noexcept {} 733a9e65961SEric Fiselier 7344e0ea2cfSLouis Dionne template <class _InPlaceT, class... _Args, class = enable_if_t< 7353359a17bSEric Fiselier _And< 7363359a17bSEric Fiselier _IsSame<_InPlaceT, in_place_t>, 73786af6f50SEric Fiselier is_constructible<value_type, _Args...> 73886af6f50SEric Fiselier >::value 73986af6f50SEric Fiselier > 740a9e65961SEric Fiselier > 741a9e65961SEric Fiselier _LIBCPP_INLINE_VISIBILITY 74286af6f50SEric Fiselier constexpr explicit optional(_InPlaceT, _Args&&... __args) 743a9e65961SEric Fiselier : __base(in_place, _VSTD::forward<_Args>(__args)...) {} 744a9e65961SEric Fiselier 7454e0ea2cfSLouis Dionne template <class _Up, class... _Args, class = enable_if_t< 746a9e65961SEric Fiselier is_constructible_v<value_type, initializer_list<_Up>&, _Args...>> 747a9e65961SEric Fiselier > 748a9e65961SEric Fiselier _LIBCPP_INLINE_VISIBILITY 749a9e65961SEric Fiselier constexpr explicit optional(in_place_t, initializer_list<_Up> __il, _Args&&... __args) 750a9e65961SEric Fiselier : __base(in_place, __il, _VSTD::forward<_Args>(__args)...) {} 751a9e65961SEric Fiselier 7524e0ea2cfSLouis Dionne template <class _Up = value_type, enable_if_t< 753a9e65961SEric Fiselier _CheckOptionalArgsCtor<_Up>::template __enable_implicit<_Up>() 754a9e65961SEric Fiselier , int> = 0> 755a9e65961SEric Fiselier _LIBCPP_INLINE_VISIBILITY 756a9e65961SEric Fiselier constexpr optional(_Up&& __v) 757a9e65961SEric Fiselier : __base(in_place, _VSTD::forward<_Up>(__v)) {} 758a9e65961SEric Fiselier 7594e0ea2cfSLouis Dionne template <class _Up, enable_if_t< 760a9e65961SEric Fiselier _CheckOptionalArgsCtor<_Up>::template __enable_explicit<_Up>() 761a9e65961SEric Fiselier , int> = 0> 762a9e65961SEric Fiselier _LIBCPP_INLINE_VISIBILITY 763a9e65961SEric Fiselier constexpr explicit optional(_Up&& __v) 764a9e65961SEric Fiselier : __base(in_place, _VSTD::forward<_Up>(__v)) {} 765a9e65961SEric Fiselier 766a9e65961SEric Fiselier // LWG2756: conditionally explicit conversion from const optional<_Up>& 7674e0ea2cfSLouis Dionne template <class _Up, enable_if_t< 768a9e65961SEric Fiselier _CheckOptionalLikeCtor<_Up, _Up const&>::template __enable_implicit<_Up>() 769a9e65961SEric Fiselier , int> = 0> 770a9e65961SEric Fiselier _LIBCPP_INLINE_VISIBILITY 77154644993SChristopher Di Bella _LIBCPP_CONSTEXPR_AFTER_CXX17 optional(const optional<_Up>& __v) 772a9e65961SEric Fiselier { 773a9e65961SEric Fiselier this->__construct_from(__v); 774a9e65961SEric Fiselier } 7754e0ea2cfSLouis Dionne template <class _Up, enable_if_t< 776a9e65961SEric Fiselier _CheckOptionalLikeCtor<_Up, _Up const&>::template __enable_explicit<_Up>() 777a9e65961SEric Fiselier , int> = 0> 778a9e65961SEric Fiselier _LIBCPP_INLINE_VISIBILITY 77954644993SChristopher Di Bella _LIBCPP_CONSTEXPR_AFTER_CXX17 explicit optional(const optional<_Up>& __v) 780a9e65961SEric Fiselier { 781a9e65961SEric Fiselier this->__construct_from(__v); 782a9e65961SEric Fiselier } 783a9e65961SEric Fiselier 784a9e65961SEric Fiselier // LWG2756: conditionally explicit conversion from optional<_Up>&& 7854e0ea2cfSLouis Dionne template <class _Up, enable_if_t< 786a9e65961SEric Fiselier _CheckOptionalLikeCtor<_Up, _Up &&>::template __enable_implicit<_Up>() 787a9e65961SEric Fiselier , int> = 0> 788a9e65961SEric Fiselier _LIBCPP_INLINE_VISIBILITY 78954644993SChristopher Di Bella _LIBCPP_CONSTEXPR_AFTER_CXX17 optional(optional<_Up>&& __v) 790a9e65961SEric Fiselier { 791a9e65961SEric Fiselier this->__construct_from(_VSTD::move(__v)); 792a9e65961SEric Fiselier } 7934e0ea2cfSLouis Dionne template <class _Up, enable_if_t< 794a9e65961SEric Fiselier _CheckOptionalLikeCtor<_Up, _Up &&>::template __enable_explicit<_Up>() 795a9e65961SEric Fiselier , int> = 0> 796a9e65961SEric Fiselier _LIBCPP_INLINE_VISIBILITY 79754644993SChristopher Di Bella _LIBCPP_CONSTEXPR_AFTER_CXX17 explicit optional(optional<_Up>&& __v) 798a9e65961SEric Fiselier { 799a9e65961SEric Fiselier this->__construct_from(_VSTD::move(__v)); 800a9e65961SEric Fiselier } 801a9e65961SEric Fiselier 80217cfc57dSNikolas Klauser#if _LIBCPP_STD_VER > 20 80317cfc57dSNikolas Klauser template<class _Fp, class... _Args> 80417cfc57dSNikolas Klauser _LIBCPP_HIDE_FROM_ABI 80517cfc57dSNikolas Klauser constexpr explicit optional(__optional_construct_from_invoke_tag, _Fp&& __f, _Args&&... __args) 80617cfc57dSNikolas Klauser : __base(__optional_construct_from_invoke_tag{}, _VSTD::forward<_Fp>(__f), _VSTD::forward<_Args>(__args)...) { 80717cfc57dSNikolas Klauser } 80817cfc57dSNikolas Klauser#endif 80917cfc57dSNikolas Klauser 810a9e65961SEric Fiselier _LIBCPP_INLINE_VISIBILITY 81154644993SChristopher Di Bella _LIBCPP_CONSTEXPR_AFTER_CXX17 optional& operator=(nullopt_t) noexcept 812a9e65961SEric Fiselier { 813a9e65961SEric Fiselier reset(); 814a9e65961SEric Fiselier return *this; 815a9e65961SEric Fiselier } 816a9e65961SEric Fiselier 817a9e65961SEric Fiselier _LIBCPP_INLINE_VISIBILITY optional& operator=(const optional&) = default; 818a9e65961SEric Fiselier _LIBCPP_INLINE_VISIBILITY optional& operator=(optional&&) = default; 819a9e65961SEric Fiselier 820a9e65961SEric Fiselier // LWG2756 821a9e65961SEric Fiselier template <class _Up = value_type, 8224e0ea2cfSLouis Dionne class = enable_if_t< 8233359a17bSEric Fiselier _And< 8243359a17bSEric Fiselier _IsNotSame<__uncvref_t<_Up>, optional>, 8253359a17bSEric Fiselier _Or< 826954014a0SMarshall Clow _IsNotSame<__uncvref_t<_Up>, value_type>, 8273359a17bSEric Fiselier _Not<is_scalar<value_type>> 828015fcffdSEric Fiselier >, 829015fcffdSEric Fiselier is_constructible<value_type, _Up>, 830015fcffdSEric Fiselier is_assignable<value_type&, _Up> 831015fcffdSEric Fiselier >::value> 832a9e65961SEric Fiselier > 833a9e65961SEric Fiselier _LIBCPP_INLINE_VISIBILITY 83454644993SChristopher Di Bella _LIBCPP_CONSTEXPR_AFTER_CXX17 optional& 835a9e65961SEric Fiselier operator=(_Up&& __v) 836a9e65961SEric Fiselier { 837a9e65961SEric Fiselier if (this->has_value()) 838a9e65961SEric Fiselier this->__get() = _VSTD::forward<_Up>(__v); 839a9e65961SEric Fiselier else 840a9e65961SEric Fiselier this->__construct(_VSTD::forward<_Up>(__v)); 841a9e65961SEric Fiselier return *this; 842a9e65961SEric Fiselier } 843a9e65961SEric Fiselier 844a9e65961SEric Fiselier // LWG2756 8454e0ea2cfSLouis Dionne template <class _Up, enable_if_t< 846a9e65961SEric Fiselier _CheckOptionalLikeAssign<_Up, _Up const&>::template __enable_assign<_Up>() 847a9e65961SEric Fiselier , int> = 0> 848a9e65961SEric Fiselier _LIBCPP_INLINE_VISIBILITY 84954644993SChristopher Di Bella _LIBCPP_CONSTEXPR_AFTER_CXX17 optional& 850a9e65961SEric Fiselier operator=(const optional<_Up>& __v) 851a9e65961SEric Fiselier { 852a9e65961SEric Fiselier this->__assign_from(__v); 853a9e65961SEric Fiselier return *this; 854a9e65961SEric Fiselier } 855a9e65961SEric Fiselier 856a9e65961SEric Fiselier // LWG2756 8574e0ea2cfSLouis Dionne template <class _Up, enable_if_t< 858a9e65961SEric Fiselier _CheckOptionalLikeCtor<_Up, _Up &&>::template __enable_assign<_Up>() 859a9e65961SEric Fiselier , int> = 0> 860a9e65961SEric Fiselier _LIBCPP_INLINE_VISIBILITY 86154644993SChristopher Di Bella _LIBCPP_CONSTEXPR_AFTER_CXX17 optional& 862a9e65961SEric Fiselier operator=(optional<_Up>&& __v) 863a9e65961SEric Fiselier { 864a9e65961SEric Fiselier this->__assign_from(_VSTD::move(__v)); 865a9e65961SEric Fiselier return *this; 866a9e65961SEric Fiselier } 867a9e65961SEric Fiselier 868a9e65961SEric Fiselier template <class... _Args, 8694e0ea2cfSLouis Dionne class = enable_if_t 870a9e65961SEric Fiselier < 871a9e65961SEric Fiselier is_constructible_v<value_type, _Args...> 872a9e65961SEric Fiselier > 873a9e65961SEric Fiselier > 874a9e65961SEric Fiselier _LIBCPP_INLINE_VISIBILITY 87554644993SChristopher Di Bella _LIBCPP_CONSTEXPR_AFTER_CXX17 _Tp & 876a9e65961SEric Fiselier emplace(_Args&&... __args) 877a9e65961SEric Fiselier { 878a9e65961SEric Fiselier reset(); 879a9e65961SEric Fiselier this->__construct(_VSTD::forward<_Args>(__args)...); 8805c80f4f6SMarshall Clow return this->__get(); 881a9e65961SEric Fiselier } 882a9e65961SEric Fiselier 883a9e65961SEric Fiselier template <class _Up, class... _Args, 8844e0ea2cfSLouis Dionne class = enable_if_t 885a9e65961SEric Fiselier < 886a9e65961SEric Fiselier is_constructible_v<value_type, initializer_list<_Up>&, _Args...> 887a9e65961SEric Fiselier > 888a9e65961SEric Fiselier > 889a9e65961SEric Fiselier _LIBCPP_INLINE_VISIBILITY 89054644993SChristopher Di Bella _LIBCPP_CONSTEXPR_AFTER_CXX17 _Tp & 891a9e65961SEric Fiselier emplace(initializer_list<_Up> __il, _Args&&... __args) 892a9e65961SEric Fiselier { 893a9e65961SEric Fiselier reset(); 894a9e65961SEric Fiselier this->__construct(__il, _VSTD::forward<_Args>(__args)...); 8955c80f4f6SMarshall Clow return this->__get(); 896a9e65961SEric Fiselier } 897a9e65961SEric Fiselier 898a9e65961SEric Fiselier _LIBCPP_INLINE_VISIBILITY 89954644993SChristopher Di Bella _LIBCPP_CONSTEXPR_AFTER_CXX17 void swap(optional& __opt) 900a9e65961SEric Fiselier noexcept(is_nothrow_move_constructible_v<value_type> && 901a9e65961SEric Fiselier is_nothrow_swappable_v<value_type>) 902a9e65961SEric Fiselier { 903a9e65961SEric Fiselier if (this->has_value() == __opt.has_value()) 904a9e65961SEric Fiselier { 905a9e65961SEric Fiselier using _VSTD::swap; 906a9e65961SEric Fiselier if (this->has_value()) 907a9e65961SEric Fiselier swap(this->__get(), __opt.__get()); 908a9e65961SEric Fiselier } 909a9e65961SEric Fiselier else 910a9e65961SEric Fiselier { 911a9e65961SEric Fiselier if (this->has_value()) 912a9e65961SEric Fiselier { 913a9e65961SEric Fiselier __opt.__construct(_VSTD::move(this->__get())); 914a9e65961SEric Fiselier reset(); 915a9e65961SEric Fiselier } 916a9e65961SEric Fiselier else 917a9e65961SEric Fiselier { 918a9e65961SEric Fiselier this->__construct(_VSTD::move(__opt.__get())); 919a9e65961SEric Fiselier __opt.reset(); 920a9e65961SEric Fiselier } 921a9e65961SEric Fiselier } 922a9e65961SEric Fiselier } 923a9e65961SEric Fiselier 924a9e65961SEric Fiselier _LIBCPP_INLINE_VISIBILITY 925a9e65961SEric Fiselier constexpr 926a9e65961SEric Fiselier add_pointer_t<value_type const> 927a9e65961SEric Fiselier operator->() const 928a9e65961SEric Fiselier { 92996100f15SKristina Bessonova _LIBCPP_ASSERT(this->has_value(), "optional operator-> called on a disengaged value"); 930a9e65961SEric Fiselier return _VSTD::addressof(this->__get()); 931a9e65961SEric Fiselier } 932a9e65961SEric Fiselier 933a9e65961SEric Fiselier _LIBCPP_INLINE_VISIBILITY 934a9e65961SEric Fiselier constexpr 935a9e65961SEric Fiselier add_pointer_t<value_type> 936a9e65961SEric Fiselier operator->() 937a9e65961SEric Fiselier { 93896100f15SKristina Bessonova _LIBCPP_ASSERT(this->has_value(), "optional operator-> called on a disengaged value"); 939a9e65961SEric Fiselier return _VSTD::addressof(this->__get()); 940a9e65961SEric Fiselier } 941a9e65961SEric Fiselier 942a9e65961SEric Fiselier _LIBCPP_INLINE_VISIBILITY 943a9e65961SEric Fiselier constexpr 944a9e65961SEric Fiselier const value_type& 94500044421Szoecarver operator*() const& noexcept 946a9e65961SEric Fiselier { 94796100f15SKristina Bessonova _LIBCPP_ASSERT(this->has_value(), "optional operator* called on a disengaged value"); 948a9e65961SEric Fiselier return this->__get(); 949a9e65961SEric Fiselier } 950a9e65961SEric Fiselier 951a9e65961SEric Fiselier _LIBCPP_INLINE_VISIBILITY 952a9e65961SEric Fiselier constexpr 953a9e65961SEric Fiselier value_type& 95400044421Szoecarver operator*() & noexcept 955a9e65961SEric Fiselier { 95696100f15SKristina Bessonova _LIBCPP_ASSERT(this->has_value(), "optional operator* called on a disengaged value"); 957a9e65961SEric Fiselier return this->__get(); 958a9e65961SEric Fiselier } 959a9e65961SEric Fiselier 960a9e65961SEric Fiselier _LIBCPP_INLINE_VISIBILITY 961a9e65961SEric Fiselier constexpr 962a9e65961SEric Fiselier value_type&& 96300044421Szoecarver operator*() && noexcept 964a9e65961SEric Fiselier { 96596100f15SKristina Bessonova _LIBCPP_ASSERT(this->has_value(), "optional operator* called on a disengaged value"); 966a9e65961SEric Fiselier return _VSTD::move(this->__get()); 967a9e65961SEric Fiselier } 968a9e65961SEric Fiselier 969a9e65961SEric Fiselier _LIBCPP_INLINE_VISIBILITY 970a9e65961SEric Fiselier constexpr 971a9e65961SEric Fiselier const value_type&& 97200044421Szoecarver operator*() const&& noexcept 973a9e65961SEric Fiselier { 97496100f15SKristina Bessonova _LIBCPP_ASSERT(this->has_value(), "optional operator* called on a disengaged value"); 975a9e65961SEric Fiselier return _VSTD::move(this->__get()); 976a9e65961SEric Fiselier } 977a9e65961SEric Fiselier 978a9e65961SEric Fiselier _LIBCPP_INLINE_VISIBILITY 979a9e65961SEric Fiselier constexpr explicit operator bool() const noexcept { return has_value(); } 980a9e65961SEric Fiselier 981a9e65961SEric Fiselier using __base::has_value; 982a9e65961SEric Fiselier using __base::__get; 983a9e65961SEric Fiselier 984a9e65961SEric Fiselier _LIBCPP_INLINE_VISIBILITY 9858a063df1SLouis Dionne _LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS 986a9e65961SEric Fiselier constexpr value_type const& value() const& 987a9e65961SEric Fiselier { 988a9e65961SEric Fiselier if (!this->has_value()) 989a9e65961SEric Fiselier __throw_bad_optional_access(); 990a9e65961SEric Fiselier return this->__get(); 991a9e65961SEric Fiselier } 992a9e65961SEric Fiselier 993a9e65961SEric Fiselier _LIBCPP_INLINE_VISIBILITY 9948a063df1SLouis Dionne _LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS 995a9e65961SEric Fiselier constexpr value_type& value() & 996a9e65961SEric Fiselier { 997a9e65961SEric Fiselier if (!this->has_value()) 998a9e65961SEric Fiselier __throw_bad_optional_access(); 999a9e65961SEric Fiselier return this->__get(); 1000a9e65961SEric Fiselier } 1001a9e65961SEric Fiselier 1002a9e65961SEric Fiselier _LIBCPP_INLINE_VISIBILITY 10038a063df1SLouis Dionne _LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS 1004a9e65961SEric Fiselier constexpr value_type&& value() && 1005a9e65961SEric Fiselier { 1006a9e65961SEric Fiselier if (!this->has_value()) 1007a9e65961SEric Fiselier __throw_bad_optional_access(); 1008a9e65961SEric Fiselier return _VSTD::move(this->__get()); 1009a9e65961SEric Fiselier } 1010a9e65961SEric Fiselier 1011a9e65961SEric Fiselier _LIBCPP_INLINE_VISIBILITY 10128a063df1SLouis Dionne _LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS 1013a9e65961SEric Fiselier constexpr value_type const&& value() const&& 1014a9e65961SEric Fiselier { 1015a9e65961SEric Fiselier if (!this->has_value()) 1016a9e65961SEric Fiselier __throw_bad_optional_access(); 1017a9e65961SEric Fiselier return _VSTD::move(this->__get()); 1018a9e65961SEric Fiselier } 1019a9e65961SEric Fiselier 1020a9e65961SEric Fiselier template <class _Up> 1021a9e65961SEric Fiselier _LIBCPP_INLINE_VISIBILITY 1022a9e65961SEric Fiselier constexpr value_type value_or(_Up&& __v) const& 1023a9e65961SEric Fiselier { 1024a9e65961SEric Fiselier static_assert(is_copy_constructible_v<value_type>, 1025a9e65961SEric Fiselier "optional<T>::value_or: T must be copy constructible"); 1026a9e65961SEric Fiselier static_assert(is_convertible_v<_Up, value_type>, 1027a9e65961SEric Fiselier "optional<T>::value_or: U must be convertible to T"); 1028a9e65961SEric Fiselier return this->has_value() ? this->__get() : 1029a9e65961SEric Fiselier static_cast<value_type>(_VSTD::forward<_Up>(__v)); 1030a9e65961SEric Fiselier } 1031a9e65961SEric Fiselier 1032a9e65961SEric Fiselier template <class _Up> 1033a9e65961SEric Fiselier _LIBCPP_INLINE_VISIBILITY 1034dd7c68bcSCasey Carter constexpr value_type value_or(_Up&& __v) && 1035a9e65961SEric Fiselier { 1036a9e65961SEric Fiselier static_assert(is_move_constructible_v<value_type>, 1037a9e65961SEric Fiselier "optional<T>::value_or: T must be move constructible"); 1038a9e65961SEric Fiselier static_assert(is_convertible_v<_Up, value_type>, 1039a9e65961SEric Fiselier "optional<T>::value_or: U must be convertible to T"); 1040a9e65961SEric Fiselier return this->has_value() ? _VSTD::move(this->__get()) : 1041a9e65961SEric Fiselier static_cast<value_type>(_VSTD::forward<_Up>(__v)); 1042a9e65961SEric Fiselier } 1043a9e65961SEric Fiselier 104417cfc57dSNikolas Klauser#if _LIBCPP_STD_VER > 20 104517cfc57dSNikolas Klauser template<class _Func> 104617cfc57dSNikolas Klauser _LIBCPP_HIDE_FROM_ABI 104717cfc57dSNikolas Klauser constexpr auto and_then(_Func&& __f) & { 104817cfc57dSNikolas Klauser using _Up = invoke_result_t<_Func, value_type&>; 104917cfc57dSNikolas Klauser static_assert(__is_std_optional<remove_cvref_t<_Up>>::value, 105017cfc57dSNikolas Klauser "Result of f(value()) must be a specialization of std::optional"); 105117cfc57dSNikolas Klauser if (*this) 105217cfc57dSNikolas Klauser return _VSTD::invoke(_VSTD::forward<_Func>(__f), value()); 105317cfc57dSNikolas Klauser return remove_cvref_t<_Up>(); 105417cfc57dSNikolas Klauser } 105517cfc57dSNikolas Klauser 105617cfc57dSNikolas Klauser template<class _Func> 105717cfc57dSNikolas Klauser _LIBCPP_HIDE_FROM_ABI 105817cfc57dSNikolas Klauser constexpr auto and_then(_Func&& __f) const& { 105917cfc57dSNikolas Klauser using _Up = invoke_result_t<_Func, const value_type&>; 106017cfc57dSNikolas Klauser static_assert(__is_std_optional<remove_cvref_t<_Up>>::value, 106117cfc57dSNikolas Klauser "Result of f(value()) must be a specialization of std::optional"); 106217cfc57dSNikolas Klauser if (*this) 106317cfc57dSNikolas Klauser return _VSTD::invoke(_VSTD::forward<_Func>(__f), value()); 106417cfc57dSNikolas Klauser return remove_cvref_t<_Up>(); 106517cfc57dSNikolas Klauser } 106617cfc57dSNikolas Klauser 106717cfc57dSNikolas Klauser template<class _Func> 106817cfc57dSNikolas Klauser _LIBCPP_HIDE_FROM_ABI 106917cfc57dSNikolas Klauser constexpr auto and_then(_Func&& __f) && { 107017cfc57dSNikolas Klauser using _Up = invoke_result_t<_Func, value_type&&>; 107117cfc57dSNikolas Klauser static_assert(__is_std_optional<remove_cvref_t<_Up>>::value, 107217cfc57dSNikolas Klauser "Result of f(std::move(value())) must be a specialization of std::optional"); 107317cfc57dSNikolas Klauser if (*this) 107417cfc57dSNikolas Klauser return _VSTD::invoke(_VSTD::forward<_Func>(__f), _VSTD::move(value())); 107517cfc57dSNikolas Klauser return remove_cvref_t<_Up>(); 107617cfc57dSNikolas Klauser } 107717cfc57dSNikolas Klauser 107817cfc57dSNikolas Klauser template<class _Func> 107917cfc57dSNikolas Klauser _LIBCPP_HIDE_FROM_ABI 108017cfc57dSNikolas Klauser constexpr auto and_then(_Func&& __f) const&& { 108117cfc57dSNikolas Klauser using _Up = invoke_result_t<_Func, const value_type&&>; 108217cfc57dSNikolas Klauser static_assert(__is_std_optional<remove_cvref_t<_Up>>::value, 108317cfc57dSNikolas Klauser "Result of f(std::move(value())) must be a specialization of std::optional"); 108417cfc57dSNikolas Klauser if (*this) 108517cfc57dSNikolas Klauser return _VSTD::invoke(_VSTD::forward<_Func>(__f), _VSTD::move(value())); 108617cfc57dSNikolas Klauser return remove_cvref_t<_Up>(); 108717cfc57dSNikolas Klauser } 108817cfc57dSNikolas Klauser 108917cfc57dSNikolas Klauser template<class _Func> 109017cfc57dSNikolas Klauser _LIBCPP_HIDE_FROM_ABI 109117cfc57dSNikolas Klauser constexpr auto transform(_Func&& __f) & { 109217cfc57dSNikolas Klauser using _Up = remove_cv_t<invoke_result_t<_Func, value_type&>>; 109317cfc57dSNikolas Klauser static_assert(!is_array_v<_Up>, "Result of f(value()) should not be an Array"); 109417cfc57dSNikolas Klauser static_assert(!is_same_v<_Up, in_place_t>, 109517cfc57dSNikolas Klauser "Result of f(value()) should not be std::in_place_t"); 109617cfc57dSNikolas Klauser static_assert(!is_same_v<_Up, nullopt_t>, 109717cfc57dSNikolas Klauser "Result of f(value()) should not be std::nullopt_t"); 109817cfc57dSNikolas Klauser static_assert(is_object_v<_Up>, "Result of f(value()) should be an object type"); 109917cfc57dSNikolas Klauser if (*this) 110017cfc57dSNikolas Klauser return optional<_Up>(__optional_construct_from_invoke_tag{}, _VSTD::forward<_Func>(__f), value()); 110117cfc57dSNikolas Klauser return optional<_Up>(); 110217cfc57dSNikolas Klauser } 110317cfc57dSNikolas Klauser 110417cfc57dSNikolas Klauser template<class _Func> 110517cfc57dSNikolas Klauser _LIBCPP_HIDE_FROM_ABI 110617cfc57dSNikolas Klauser constexpr auto transform(_Func&& __f) const& { 110717cfc57dSNikolas Klauser using _Up = remove_cv_t<invoke_result_t<_Func, const value_type&>>; 110817cfc57dSNikolas Klauser static_assert(!is_array_v<_Up>, "Result of f(value()) should not be an Array"); 110917cfc57dSNikolas Klauser static_assert(!is_same_v<_Up, in_place_t>, 111017cfc57dSNikolas Klauser "Result of f(value()) should not be std::in_place_t"); 111117cfc57dSNikolas Klauser static_assert(!is_same_v<_Up, nullopt_t>, 111217cfc57dSNikolas Klauser "Result of f(value()) should not be std::nullopt_t"); 111317cfc57dSNikolas Klauser static_assert(is_object_v<_Up>, "Result of f(value()) should be an object type"); 111417cfc57dSNikolas Klauser if (*this) 111517cfc57dSNikolas Klauser return optional<_Up>(__optional_construct_from_invoke_tag{}, _VSTD::forward<_Func>(__f), value()); 111617cfc57dSNikolas Klauser return optional<_Up>(); 111717cfc57dSNikolas Klauser } 111817cfc57dSNikolas Klauser 111917cfc57dSNikolas Klauser template<class _Func> 112017cfc57dSNikolas Klauser _LIBCPP_HIDE_FROM_ABI 112117cfc57dSNikolas Klauser constexpr auto transform(_Func&& __f) && { 112217cfc57dSNikolas Klauser using _Up = remove_cv_t<invoke_result_t<_Func, value_type&&>>; 112317cfc57dSNikolas Klauser static_assert(!is_array_v<_Up>, "Result of f(std::move(value())) should not be an Array"); 112417cfc57dSNikolas Klauser static_assert(!is_same_v<_Up, in_place_t>, 112517cfc57dSNikolas Klauser "Result of f(std::move(value())) should not be std::in_place_t"); 112617cfc57dSNikolas Klauser static_assert(!is_same_v<_Up, nullopt_t>, 112717cfc57dSNikolas Klauser "Result of f(std::move(value())) should not be std::nullopt_t"); 112817cfc57dSNikolas Klauser static_assert(is_object_v<_Up>, "Result of f(std::move(value())) should be an object type"); 112917cfc57dSNikolas Klauser if (*this) 113017cfc57dSNikolas Klauser return optional<_Up>(__optional_construct_from_invoke_tag{}, _VSTD::forward<_Func>(__f), _VSTD::move(value())); 113117cfc57dSNikolas Klauser return optional<_Up>(); 113217cfc57dSNikolas Klauser } 113317cfc57dSNikolas Klauser 113417cfc57dSNikolas Klauser template<class _Func> 113517cfc57dSNikolas Klauser _LIBCPP_HIDE_FROM_ABI 113617cfc57dSNikolas Klauser constexpr auto transform(_Func&& __f) const&& { 113717cfc57dSNikolas Klauser using _Up = remove_cvref_t<invoke_result_t<_Func, const value_type&&>>; 113817cfc57dSNikolas Klauser static_assert(!is_array_v<_Up>, "Result of f(std::move(value())) should not be an Array"); 113917cfc57dSNikolas Klauser static_assert(!is_same_v<_Up, in_place_t>, 114017cfc57dSNikolas Klauser "Result of f(std::move(value())) should not be std::in_place_t"); 114117cfc57dSNikolas Klauser static_assert(!is_same_v<_Up, nullopt_t>, 114217cfc57dSNikolas Klauser "Result of f(std::move(value())) should not be std::nullopt_t"); 114317cfc57dSNikolas Klauser static_assert(is_object_v<_Up>, "Result of f(std::move(value())) should be an object type"); 114417cfc57dSNikolas Klauser if (*this) 114517cfc57dSNikolas Klauser return optional<_Up>(__optional_construct_from_invoke_tag{}, _VSTD::forward<_Func>(__f), _VSTD::move(value())); 114617cfc57dSNikolas Klauser return optional<_Up>(); 114717cfc57dSNikolas Klauser } 114817cfc57dSNikolas Klauser 114917cfc57dSNikolas Klauser template<invocable _Func> 115017cfc57dSNikolas Klauser _LIBCPP_HIDE_FROM_ABI 115117cfc57dSNikolas Klauser constexpr optional or_else(_Func&& __f) const& requires is_copy_constructible_v<value_type> { 115217cfc57dSNikolas Klauser static_assert(is_same_v<remove_cvref_t<invoke_result_t<_Func>>, optional>, 115317cfc57dSNikolas Klauser "Result of f() should be the same type as this optional"); 115417cfc57dSNikolas Klauser if (*this) 115517cfc57dSNikolas Klauser return *this; 115617cfc57dSNikolas Klauser return _VSTD::forward<_Func>(__f)(); 115717cfc57dSNikolas Klauser } 115817cfc57dSNikolas Klauser 115917cfc57dSNikolas Klauser template<invocable _Func> 116017cfc57dSNikolas Klauser _LIBCPP_HIDE_FROM_ABI 116117cfc57dSNikolas Klauser constexpr optional or_else(_Func&& __f) && requires is_move_constructible_v<value_type> { 116217cfc57dSNikolas Klauser static_assert(is_same_v<remove_cvref_t<invoke_result_t<_Func>>, optional>, 116317cfc57dSNikolas Klauser "Result of f() should be the same type as this optional"); 116417cfc57dSNikolas Klauser if (*this) 116517cfc57dSNikolas Klauser return _VSTD::move(*this); 116617cfc57dSNikolas Klauser return _VSTD::forward<_Func>(__f)(); 116717cfc57dSNikolas Klauser } 116817cfc57dSNikolas Klauser#endif // _LIBCPP_STD_VER > 20 116917cfc57dSNikolas Klauser 1170a9e65961SEric Fiselier using __base::reset; 1171a9e65961SEric Fiselier}; 1172a9e65961SEric Fiselier 117301666904SLouis Dionne#if _LIBCPP_STD_VER >= 17 1174a8f1a715SArthur O'Dwyertemplate<class _Tp> 1175a8f1a715SArthur O'Dwyer optional(_Tp) -> optional<_Tp>; 1176f35b4bc3SMarshall Clow#endif 1177f35b4bc3SMarshall Clow 1178a9e65961SEric Fiselier// Comparisons between optionals 1179dc808af3SEric Fiseliertemplate <class _Tp, class _Up> 1180a9e65961SEric Fiselier_LIBCPP_INLINE_VISIBILITY constexpr 11814e0ea2cfSLouis Dionneenable_if_t< 1182ab3fcc50SArthur O'Dwyer is_convertible_v<decltype(declval<const _Tp&>() == 1183ab3fcc50SArthur O'Dwyer declval<const _Up&>()), bool>, 1184a9e65961SEric Fiselier bool 1185a9e65961SEric Fiselier> 1186dc808af3SEric Fiselieroperator==(const optional<_Tp>& __x, const optional<_Up>& __y) 1187a9e65961SEric Fiselier{ 1188a9e65961SEric Fiselier if (static_cast<bool>(__x) != static_cast<bool>(__y)) 1189a9e65961SEric Fiselier return false; 1190a9e65961SEric Fiselier if (!static_cast<bool>(__x)) 1191a9e65961SEric Fiselier return true; 1192a9e65961SEric Fiselier return *__x == *__y; 1193a9e65961SEric Fiselier} 1194a9e65961SEric Fiselier 1195dc808af3SEric Fiseliertemplate <class _Tp, class _Up> 1196a9e65961SEric Fiselier_LIBCPP_INLINE_VISIBILITY constexpr 11974e0ea2cfSLouis Dionneenable_if_t< 1198ab3fcc50SArthur O'Dwyer is_convertible_v<decltype(declval<const _Tp&>() != 1199ab3fcc50SArthur O'Dwyer declval<const _Up&>()), bool>, 1200a9e65961SEric Fiselier bool 1201a9e65961SEric Fiselier> 1202dc808af3SEric Fiselieroperator!=(const optional<_Tp>& __x, const optional<_Up>& __y) 1203a9e65961SEric Fiselier{ 1204a9e65961SEric Fiselier if (static_cast<bool>(__x) != static_cast<bool>(__y)) 1205a9e65961SEric Fiselier return true; 1206a9e65961SEric Fiselier if (!static_cast<bool>(__x)) 1207a9e65961SEric Fiselier return false; 1208a9e65961SEric Fiselier return *__x != *__y; 1209a9e65961SEric Fiselier} 1210a9e65961SEric Fiselier 1211dc808af3SEric Fiseliertemplate <class _Tp, class _Up> 1212a9e65961SEric Fiselier_LIBCPP_INLINE_VISIBILITY constexpr 12134e0ea2cfSLouis Dionneenable_if_t< 1214ab3fcc50SArthur O'Dwyer is_convertible_v<decltype(declval<const _Tp&>() < 1215ab3fcc50SArthur O'Dwyer declval<const _Up&>()), bool>, 1216a9e65961SEric Fiselier bool 1217a9e65961SEric Fiselier> 1218dc808af3SEric Fiselieroperator<(const optional<_Tp>& __x, const optional<_Up>& __y) 1219a9e65961SEric Fiselier{ 1220a9e65961SEric Fiselier if (!static_cast<bool>(__y)) 1221a9e65961SEric Fiselier return false; 1222a9e65961SEric Fiselier if (!static_cast<bool>(__x)) 1223a9e65961SEric Fiselier return true; 1224a9e65961SEric Fiselier return *__x < *__y; 1225a9e65961SEric Fiselier} 1226a9e65961SEric Fiselier 1227dc808af3SEric Fiseliertemplate <class _Tp, class _Up> 1228a9e65961SEric Fiselier_LIBCPP_INLINE_VISIBILITY constexpr 12294e0ea2cfSLouis Dionneenable_if_t< 1230ab3fcc50SArthur O'Dwyer is_convertible_v<decltype(declval<const _Tp&>() > 1231ab3fcc50SArthur O'Dwyer declval<const _Up&>()), bool>, 1232a9e65961SEric Fiselier bool 1233a9e65961SEric Fiselier> 1234dc808af3SEric Fiselieroperator>(const optional<_Tp>& __x, const optional<_Up>& __y) 1235a9e65961SEric Fiselier{ 1236a9e65961SEric Fiselier if (!static_cast<bool>(__x)) 1237a9e65961SEric Fiselier return false; 1238a9e65961SEric Fiselier if (!static_cast<bool>(__y)) 1239a9e65961SEric Fiselier return true; 1240a9e65961SEric Fiselier return *__x > *__y; 1241a9e65961SEric Fiselier} 1242a9e65961SEric Fiselier 1243dc808af3SEric Fiseliertemplate <class _Tp, class _Up> 1244a9e65961SEric Fiselier_LIBCPP_INLINE_VISIBILITY constexpr 12454e0ea2cfSLouis Dionneenable_if_t< 1246ab3fcc50SArthur O'Dwyer is_convertible_v<decltype(declval<const _Tp&>() <= 1247ab3fcc50SArthur O'Dwyer declval<const _Up&>()), bool>, 1248a9e65961SEric Fiselier bool 1249a9e65961SEric Fiselier> 1250dc808af3SEric Fiselieroperator<=(const optional<_Tp>& __x, const optional<_Up>& __y) 1251a9e65961SEric Fiselier{ 1252a9e65961SEric Fiselier if (!static_cast<bool>(__x)) 1253a9e65961SEric Fiselier return true; 1254a9e65961SEric Fiselier if (!static_cast<bool>(__y)) 1255a9e65961SEric Fiselier return false; 1256a9e65961SEric Fiselier return *__x <= *__y; 1257a9e65961SEric Fiselier} 1258a9e65961SEric Fiselier 1259dc808af3SEric Fiseliertemplate <class _Tp, class _Up> 1260a9e65961SEric Fiselier_LIBCPP_INLINE_VISIBILITY constexpr 12614e0ea2cfSLouis Dionneenable_if_t< 1262ab3fcc50SArthur O'Dwyer is_convertible_v<decltype(declval<const _Tp&>() >= 1263ab3fcc50SArthur O'Dwyer declval<const _Up&>()), bool>, 1264a9e65961SEric Fiselier bool 1265a9e65961SEric Fiselier> 1266dc808af3SEric Fiselieroperator>=(const optional<_Tp>& __x, const optional<_Up>& __y) 1267a9e65961SEric Fiselier{ 1268a9e65961SEric Fiselier if (!static_cast<bool>(__y)) 1269a9e65961SEric Fiselier return true; 1270a9e65961SEric Fiselier if (!static_cast<bool>(__x)) 1271a9e65961SEric Fiselier return false; 1272a9e65961SEric Fiselier return *__x >= *__y; 1273a9e65961SEric Fiselier} 1274a9e65961SEric Fiselier 1275a9e65961SEric Fiselier// Comparisons with nullopt 1276a9e65961SEric Fiseliertemplate <class _Tp> 1277a9e65961SEric Fiselier_LIBCPP_INLINE_VISIBILITY constexpr 1278a9e65961SEric Fiselierbool 1279a9e65961SEric Fiselieroperator==(const optional<_Tp>& __x, nullopt_t) noexcept 1280a9e65961SEric Fiselier{ 1281a9e65961SEric Fiselier return !static_cast<bool>(__x); 1282a9e65961SEric Fiselier} 1283a9e65961SEric Fiselier 1284a9e65961SEric Fiseliertemplate <class _Tp> 1285a9e65961SEric Fiselier_LIBCPP_INLINE_VISIBILITY constexpr 1286a9e65961SEric Fiselierbool 1287a9e65961SEric Fiselieroperator==(nullopt_t, const optional<_Tp>& __x) 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!=(const optional<_Tp>& __x, nullopt_t) 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!=(nullopt_t, const optional<_Tp>& __x) 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<(const optional<_Tp>&, nullopt_t) noexcept 1312a9e65961SEric Fiselier{ 1313a9e65961SEric Fiselier return false; 1314a9e65961SEric Fiselier} 1315a9e65961SEric Fiselier 1316a9e65961SEric Fiseliertemplate <class _Tp> 1317a9e65961SEric Fiselier_LIBCPP_INLINE_VISIBILITY constexpr 1318a9e65961SEric Fiselierbool 1319a9e65961SEric Fiselieroperator<(nullopt_t, const optional<_Tp>& __x) noexcept 1320a9e65961SEric Fiselier{ 1321a9e65961SEric Fiselier return static_cast<bool>(__x); 1322a9e65961SEric Fiselier} 1323a9e65961SEric Fiselier 1324a9e65961SEric Fiseliertemplate <class _Tp> 1325a9e65961SEric Fiselier_LIBCPP_INLINE_VISIBILITY constexpr 1326a9e65961SEric Fiselierbool 1327a9e65961SEric Fiselieroperator<=(const optional<_Tp>& __x, nullopt_t) 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 1335fd838227SEric Fiselieroperator<=(nullopt_t, const optional<_Tp>&) noexcept 1336a9e65961SEric Fiselier{ 1337a9e65961SEric Fiselier return true; 1338a9e65961SEric Fiselier} 1339a9e65961SEric Fiselier 1340a9e65961SEric Fiseliertemplate <class _Tp> 1341a9e65961SEric Fiselier_LIBCPP_INLINE_VISIBILITY constexpr 1342a9e65961SEric Fiselierbool 1343a9e65961SEric Fiselieroperator>(const optional<_Tp>& __x, nullopt_t) noexcept 1344a9e65961SEric Fiselier{ 1345a9e65961SEric Fiselier return static_cast<bool>(__x); 1346a9e65961SEric Fiselier} 1347a9e65961SEric Fiselier 1348a9e65961SEric Fiseliertemplate <class _Tp> 1349a9e65961SEric Fiselier_LIBCPP_INLINE_VISIBILITY constexpr 1350a9e65961SEric Fiselierbool 1351fd838227SEric Fiselieroperator>(nullopt_t, const optional<_Tp>&) noexcept 1352a9e65961SEric Fiselier{ 1353a9e65961SEric Fiselier return false; 1354a9e65961SEric Fiselier} 1355a9e65961SEric Fiselier 1356a9e65961SEric Fiseliertemplate <class _Tp> 1357a9e65961SEric Fiselier_LIBCPP_INLINE_VISIBILITY constexpr 1358a9e65961SEric Fiselierbool 1359a9e65961SEric Fiselieroperator>=(const optional<_Tp>&, nullopt_t) noexcept 1360a9e65961SEric Fiselier{ 1361a9e65961SEric Fiselier return true; 1362a9e65961SEric Fiselier} 1363a9e65961SEric Fiselier 1364a9e65961SEric Fiseliertemplate <class _Tp> 1365a9e65961SEric Fiselier_LIBCPP_INLINE_VISIBILITY constexpr 1366a9e65961SEric Fiselierbool 1367a9e65961SEric Fiselieroperator>=(nullopt_t, const optional<_Tp>& __x) noexcept 1368a9e65961SEric Fiselier{ 1369a9e65961SEric Fiselier return !static_cast<bool>(__x); 1370a9e65961SEric Fiselier} 1371a9e65961SEric Fiselier 1372a9e65961SEric Fiselier// Comparisons with T 1373dc808af3SEric Fiseliertemplate <class _Tp, class _Up> 1374a9e65961SEric Fiselier_LIBCPP_INLINE_VISIBILITY constexpr 13754e0ea2cfSLouis Dionneenable_if_t< 1376ab3fcc50SArthur O'Dwyer is_convertible_v<decltype(declval<const _Tp&>() == 1377ab3fcc50SArthur O'Dwyer declval<const _Up&>()), bool>, 1378a9e65961SEric Fiselier bool 1379a9e65961SEric Fiselier> 1380dc808af3SEric Fiselieroperator==(const optional<_Tp>& __x, const _Up& __v) 1381a9e65961SEric Fiselier{ 1382a9e65961SEric Fiselier return static_cast<bool>(__x) ? *__x == __v : false; 1383a9e65961SEric Fiselier} 1384a9e65961SEric Fiselier 1385dc808af3SEric Fiseliertemplate <class _Tp, class _Up> 1386a9e65961SEric Fiselier_LIBCPP_INLINE_VISIBILITY constexpr 13874e0ea2cfSLouis Dionneenable_if_t< 1388ab3fcc50SArthur O'Dwyer is_convertible_v<decltype(declval<const _Tp&>() == 1389ab3fcc50SArthur O'Dwyer declval<const _Up&>()), bool>, 1390a9e65961SEric Fiselier bool 1391a9e65961SEric Fiselier> 1392dc808af3SEric Fiselieroperator==(const _Tp& __v, const optional<_Up>& __x) 1393a9e65961SEric Fiselier{ 1394a9e65961SEric Fiselier return static_cast<bool>(__x) ? __v == *__x : false; 1395a9e65961SEric Fiselier} 1396a9e65961SEric Fiselier 1397dc808af3SEric Fiseliertemplate <class _Tp, class _Up> 1398a9e65961SEric Fiselier_LIBCPP_INLINE_VISIBILITY constexpr 13994e0ea2cfSLouis Dionneenable_if_t< 1400ab3fcc50SArthur O'Dwyer is_convertible_v<decltype(declval<const _Tp&>() != 1401ab3fcc50SArthur O'Dwyer declval<const _Up&>()), bool>, 1402a9e65961SEric Fiselier bool 1403a9e65961SEric Fiselier> 1404dc808af3SEric Fiselieroperator!=(const optional<_Tp>& __x, const _Up& __v) 1405a9e65961SEric Fiselier{ 1406a9e65961SEric Fiselier return static_cast<bool>(__x) ? *__x != __v : true; 1407a9e65961SEric Fiselier} 1408a9e65961SEric Fiselier 1409dc808af3SEric Fiseliertemplate <class _Tp, class _Up> 1410a9e65961SEric Fiselier_LIBCPP_INLINE_VISIBILITY constexpr 14114e0ea2cfSLouis Dionneenable_if_t< 1412ab3fcc50SArthur O'Dwyer is_convertible_v<decltype(declval<const _Tp&>() != 1413ab3fcc50SArthur O'Dwyer declval<const _Up&>()), bool>, 1414a9e65961SEric Fiselier bool 1415a9e65961SEric Fiselier> 1416dc808af3SEric Fiselieroperator!=(const _Tp& __v, const optional<_Up>& __x) 1417a9e65961SEric Fiselier{ 1418a9e65961SEric Fiselier return static_cast<bool>(__x) ? __v != *__x : true; 1419a9e65961SEric Fiselier} 1420a9e65961SEric Fiselier 1421dc808af3SEric Fiseliertemplate <class _Tp, class _Up> 1422a9e65961SEric Fiselier_LIBCPP_INLINE_VISIBILITY constexpr 14234e0ea2cfSLouis Dionneenable_if_t< 1424ab3fcc50SArthur O'Dwyer is_convertible_v<decltype(declval<const _Tp&>() < 1425ab3fcc50SArthur O'Dwyer declval<const _Up&>()), bool>, 1426a9e65961SEric Fiselier bool 1427a9e65961SEric Fiselier> 1428dc808af3SEric Fiselieroperator<(const optional<_Tp>& __x, const _Up& __v) 1429a9e65961SEric Fiselier{ 1430a9e65961SEric Fiselier return static_cast<bool>(__x) ? *__x < __v : true; 1431a9e65961SEric Fiselier} 1432a9e65961SEric Fiselier 1433dc808af3SEric Fiseliertemplate <class _Tp, class _Up> 1434a9e65961SEric Fiselier_LIBCPP_INLINE_VISIBILITY constexpr 14354e0ea2cfSLouis Dionneenable_if_t< 1436ab3fcc50SArthur O'Dwyer is_convertible_v<decltype(declval<const _Tp&>() < 1437ab3fcc50SArthur O'Dwyer declval<const _Up&>()), bool>, 1438a9e65961SEric Fiselier bool 1439a9e65961SEric Fiselier> 1440dc808af3SEric Fiselieroperator<(const _Tp& __v, const optional<_Up>& __x) 1441a9e65961SEric Fiselier{ 1442a9e65961SEric Fiselier return static_cast<bool>(__x) ? __v < *__x : false; 1443a9e65961SEric Fiselier} 1444a9e65961SEric Fiselier 1445dc808af3SEric Fiseliertemplate <class _Tp, class _Up> 1446a9e65961SEric Fiselier_LIBCPP_INLINE_VISIBILITY constexpr 14474e0ea2cfSLouis Dionneenable_if_t< 1448ab3fcc50SArthur O'Dwyer is_convertible_v<decltype(declval<const _Tp&>() <= 1449ab3fcc50SArthur O'Dwyer declval<const _Up&>()), bool>, 1450a9e65961SEric Fiselier bool 1451a9e65961SEric Fiselier> 1452dc808af3SEric Fiselieroperator<=(const optional<_Tp>& __x, const _Up& __v) 1453a9e65961SEric Fiselier{ 1454a9e65961SEric Fiselier return static_cast<bool>(__x) ? *__x <= __v : true; 1455a9e65961SEric Fiselier} 1456a9e65961SEric Fiselier 1457dc808af3SEric Fiseliertemplate <class _Tp, class _Up> 1458a9e65961SEric Fiselier_LIBCPP_INLINE_VISIBILITY constexpr 14594e0ea2cfSLouis Dionneenable_if_t< 1460ab3fcc50SArthur O'Dwyer is_convertible_v<decltype(declval<const _Tp&>() <= 1461ab3fcc50SArthur O'Dwyer declval<const _Up&>()), bool>, 1462a9e65961SEric Fiselier bool 1463a9e65961SEric Fiselier> 1464dc808af3SEric Fiselieroperator<=(const _Tp& __v, const optional<_Up>& __x) 1465a9e65961SEric Fiselier{ 1466a9e65961SEric Fiselier return static_cast<bool>(__x) ? __v <= *__x : false; 1467a9e65961SEric Fiselier} 1468a9e65961SEric Fiselier 1469dc808af3SEric Fiseliertemplate <class _Tp, class _Up> 1470a9e65961SEric Fiselier_LIBCPP_INLINE_VISIBILITY constexpr 14714e0ea2cfSLouis Dionneenable_if_t< 1472ab3fcc50SArthur O'Dwyer is_convertible_v<decltype(declval<const _Tp&>() > 1473ab3fcc50SArthur O'Dwyer declval<const _Up&>()), bool>, 1474a9e65961SEric Fiselier bool 1475a9e65961SEric Fiselier> 1476dc808af3SEric Fiselieroperator>(const optional<_Tp>& __x, const _Up& __v) 1477a9e65961SEric Fiselier{ 1478a9e65961SEric Fiselier return static_cast<bool>(__x) ? *__x > __v : false; 1479a9e65961SEric Fiselier} 1480a9e65961SEric Fiselier 1481dc808af3SEric Fiseliertemplate <class _Tp, class _Up> 1482a9e65961SEric Fiselier_LIBCPP_INLINE_VISIBILITY constexpr 14834e0ea2cfSLouis Dionneenable_if_t< 1484ab3fcc50SArthur O'Dwyer is_convertible_v<decltype(declval<const _Tp&>() > 1485ab3fcc50SArthur O'Dwyer declval<const _Up&>()), bool>, 1486a9e65961SEric Fiselier bool 1487a9e65961SEric Fiselier> 1488dc808af3SEric Fiselieroperator>(const _Tp& __v, const optional<_Up>& __x) 1489a9e65961SEric Fiselier{ 1490a9e65961SEric Fiselier return static_cast<bool>(__x) ? __v > *__x : true; 1491a9e65961SEric Fiselier} 1492a9e65961SEric Fiselier 1493dc808af3SEric Fiseliertemplate <class _Tp, class _Up> 1494a9e65961SEric Fiselier_LIBCPP_INLINE_VISIBILITY constexpr 14954e0ea2cfSLouis Dionneenable_if_t< 1496ab3fcc50SArthur O'Dwyer is_convertible_v<decltype(declval<const _Tp&>() >= 1497ab3fcc50SArthur O'Dwyer declval<const _Up&>()), bool>, 1498a9e65961SEric Fiselier bool 1499a9e65961SEric Fiselier> 1500dc808af3SEric Fiselieroperator>=(const optional<_Tp>& __x, const _Up& __v) 1501a9e65961SEric Fiselier{ 1502a9e65961SEric Fiselier return static_cast<bool>(__x) ? *__x >= __v : false; 1503a9e65961SEric Fiselier} 1504a9e65961SEric Fiselier 1505dc808af3SEric Fiseliertemplate <class _Tp, class _Up> 1506a9e65961SEric Fiselier_LIBCPP_INLINE_VISIBILITY constexpr 15074e0ea2cfSLouis Dionneenable_if_t< 1508ab3fcc50SArthur O'Dwyer is_convertible_v<decltype(declval<const _Tp&>() >= 1509ab3fcc50SArthur O'Dwyer declval<const _Up&>()), bool>, 1510a9e65961SEric Fiselier bool 1511a9e65961SEric Fiselier> 1512dc808af3SEric Fiselieroperator>=(const _Tp& __v, const optional<_Up>& __x) 1513a9e65961SEric Fiselier{ 1514a9e65961SEric Fiselier return static_cast<bool>(__x) ? __v >= *__x : true; 1515a9e65961SEric Fiselier} 1516a9e65961SEric Fiselier 1517a9e65961SEric Fiselier 1518a9e65961SEric Fiseliertemplate <class _Tp> 151954644993SChristopher Di Bellainline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 15204e0ea2cfSLouis Dionneenable_if_t< 1521a9e65961SEric Fiselier is_move_constructible_v<_Tp> && is_swappable_v<_Tp>, 1522a9e65961SEric Fiselier void 1523a9e65961SEric Fiselier> 1524a9e65961SEric Fiselierswap(optional<_Tp>& __x, optional<_Tp>& __y) noexcept(noexcept(__x.swap(__y))) 1525a9e65961SEric Fiselier{ 1526a9e65961SEric Fiselier __x.swap(__y); 1527a9e65961SEric Fiselier} 1528a9e65961SEric Fiselier 1529a9e65961SEric Fiseliertemplate <class _Tp> 1530a9e65961SEric Fiselier_LIBCPP_INLINE_VISIBILITY constexpr 1531a9e65961SEric Fiselieroptional<decay_t<_Tp>> make_optional(_Tp&& __v) 1532a9e65961SEric Fiselier{ 1533a9e65961SEric Fiselier return optional<decay_t<_Tp>>(_VSTD::forward<_Tp>(__v)); 1534a9e65961SEric Fiselier} 1535a9e65961SEric Fiselier 1536a9e65961SEric Fiseliertemplate <class _Tp, class... _Args> 1537a9e65961SEric Fiselier_LIBCPP_INLINE_VISIBILITY constexpr 1538a9e65961SEric Fiselieroptional<_Tp> make_optional(_Args&&... __args) 1539a9e65961SEric Fiselier{ 1540a9e65961SEric Fiselier return optional<_Tp>(in_place, _VSTD::forward<_Args>(__args)...); 1541a9e65961SEric Fiselier} 1542a9e65961SEric Fiselier 1543a9e65961SEric Fiseliertemplate <class _Tp, class _Up, class... _Args> 1544a9e65961SEric Fiselier_LIBCPP_INLINE_VISIBILITY constexpr 1545a9e65961SEric Fiselieroptional<_Tp> make_optional(initializer_list<_Up> __il, _Args&&... __args) 1546a9e65961SEric Fiselier{ 1547a9e65961SEric Fiselier return optional<_Tp>(in_place, __il, _VSTD::forward<_Args>(__args)...); 1548a9e65961SEric Fiselier} 1549a9e65961SEric Fiselier 1550a9e65961SEric Fiseliertemplate <class _Tp> 1551f9127593SEric Fiselierstruct _LIBCPP_TEMPLATE_VIS hash< 1552f9127593SEric Fiselier __enable_hash_helper<optional<_Tp>, remove_const_t<_Tp>> 1553f9127593SEric Fiselier> 1554a9e65961SEric Fiselier{ 1555dc066888SArthur O'Dwyer#if _LIBCPP_STD_VER <= 17 || defined(_LIBCPP_ENABLE_CXX20_REMOVED_BINDER_TYPEDEFS) 1556dc066888SArthur O'Dwyer _LIBCPP_DEPRECATED_IN_CXX17 typedef optional<_Tp> argument_type; 1557dc066888SArthur O'Dwyer _LIBCPP_DEPRECATED_IN_CXX17 typedef size_t result_type; 1558dc066888SArthur O'Dwyer#endif 1559a9e65961SEric Fiselier 1560a9e65961SEric Fiselier _LIBCPP_INLINE_VISIBILITY 1561dc066888SArthur O'Dwyer size_t operator()(const optional<_Tp>& __opt) const 1562a9e65961SEric Fiselier { 1563f9127593SEric Fiselier return static_cast<bool>(__opt) ? hash<remove_const_t<_Tp>>()(*__opt) : 0; 1564a9e65961SEric Fiselier } 1565a9e65961SEric Fiselier}; 1566a9e65961SEric Fiselier 1567a9e65961SEric Fiselier_LIBCPP_END_NAMESPACE_STD 1568a9e65961SEric Fiselier 1569a9e65961SEric Fiselier#endif // _LIBCPP_STD_VER > 14 1570a9e65961SEric Fiselier 1571a9e65961SEric Fiselier#endif // _LIBCPP_OPTIONAL 1572