optional revision 261272
1261272Sdim// -*- C++ -*- 2261272Sdim//===-------------------------- optional ----------------------------------===// 3261272Sdim// 4261272Sdim// The LLVM Compiler Infrastructure 5261272Sdim// 6261272Sdim// This file is dual licensed under the MIT and the University of Illinois Open 7261272Sdim// Source Licenses. See LICENSE.TXT for details. 8261272Sdim// 9261272Sdim//===----------------------------------------------------------------------===// 10261272Sdim 11261272Sdim#ifndef _LIBCPP_OPTIONAL 12261272Sdim#define _LIBCPP_OPTIONAL 13261272Sdim 14261272Sdim/* 15261272Sdim optional synopsis 16261272Sdim 17261272Sdim// C++1y 18261272Sdim 19261272Sdim#include <initializer_list> 20261272Sdim 21261272Sdimnamespace std { namespace experimental { 22261272Sdim 23261272Sdim// optional for object types 24261272Sdimtemplate <class T> 25261272Sdimclass optional 26261272Sdim{ 27261272Sdimpublic: 28261272Sdim typedef T value_type; 29261272Sdim 30261272Sdim // constructors 31261272Sdim constexpr optional() noexcept; 32261272Sdim constexpr optional(nullopt_t) noexcept; 33261272Sdim optional(const optional&); 34261272Sdim optional(optional&&) noexcept(is_nothrow_move_constructible<T>::value); 35261272Sdim constexpr optional(const T&); 36261272Sdim constexpr optional(T&&); 37261272Sdim template <class... Args> constexpr explicit optional(in_place_t, Args&&...); 38261272Sdim template <class U, class... Args> 39261272Sdim constexpr explicit optional(in_place_t, initializer_list<U>, Args&&...); 40261272Sdim 41261272Sdim // destructor 42261272Sdim ~optional(); 43261272Sdim 44261272Sdim // assignment 45261272Sdim optional& operator=(nullopt_t) noexcept; 46261272Sdim optional& operator=(const optional&); 47261272Sdim optional& operator=(optional&&) 48261272Sdim noexcept(is_nothrow_move_assignable<T>::value && 49261272Sdim is_nothrow_move_constructible<T>::value); 50261272Sdim template <class U> optional& operator=(U&&); 51261272Sdim template <class... Args> void emplace(Args&&...); 52261272Sdim template <class U, class... Args> void emplace(initializer_list<U>, Args&&...); 53261272Sdim 54261272Sdim // swap 55261272Sdim void swap(optional&) 56261272Sdim noexcept(is_nothrow_move_constructible<T>::value && 57261272Sdim noexcept(swap(declval<T&>(), declval<T&>()))); 58261272Sdim 59261272Sdim // observers 60261272Sdim constexpr T const* operator->() const; 61261272Sdim T* operator->(); 62261272Sdim constexpr T const& operator*() const; 63261272Sdim T& operator*(); 64261272Sdim constexpr explicit operator bool() const noexcept; 65261272Sdim constexpr T const& value() const; 66261272Sdim T& value(); 67261272Sdim template <class U> constexpr T value_or(U&&) const&; 68261272Sdim template <class U> T value_or(U&&) &&; 69261272Sdim}; 70261272Sdim 71261272Sdim// In-place construction 72261272Sdimstruct in_place_t{}; 73261272Sdimconstexpr in_place_t in_place{}; 74261272Sdim 75261272Sdim// Disengaged state indicator 76261272Sdimstruct nullopt_t{see below}; 77261272Sdimconstexpr nullopt_t nullopt(unspecified); 78261272Sdim 79261272Sdim// class bad_optional_access 80261272Sdimclass bad_optional_access 81261272Sdim : public logic_error 82261272Sdim{ 83261272Sdimpublic: 84261272Sdim explicit bad_optional_access(const string& what_arg); 85261272Sdim explicit bad_optional_access(const char* what_arg); 86261272Sdim}; 87261272Sdim 88261272Sdim// Relational operators 89261272Sdimtemplate <class T> constexpr bool operator==(const optional<T>&, const optional<T>&); 90261272Sdimtemplate <class T> constexpr bool operator< (const optional<T>&, const optional<T>&); 91261272Sdim 92261272Sdim// Comparison with nullopt 93261272Sdimtemplate <class T> constexpr bool operator==(const optional<T>&, nullopt_t) noexcept; 94261272Sdimtemplate <class T> constexpr bool operator==(nullopt_t, const optional<T>&) noexcept; 95261272Sdimtemplate <class T> constexpr bool operator<(const optional<T>&, nullopt_t) noexcept; 96261272Sdimtemplate <class T> constexpr bool operator<(nullopt_t, const optional<T>&) noexcept; 97261272Sdim 98261272Sdim// Comparison with T 99261272Sdimtemplate <class T> constexpr bool operator==(const optional<T>&, const T&); 100261272Sdimtemplate <class T> constexpr bool operator==(const T&, const optional<T>&); 101261272Sdimtemplate <class T> constexpr bool operator<(const optional<T>&, const T&); 102261272Sdimtemplate <class T> constexpr bool operator<(const T&, const optional<T>&); 103261272Sdim 104261272Sdim// Specialized algorithms 105261272Sdimtemplate <class T> void swap(optional<T>&, optional<T>&) noexcept(see below); 106261272Sdimtemplate <class T> constexpr optional<typename decay<T>::type> make_optional(T&&); 107261272Sdim 108261272Sdim// hash support 109261272Sdimtemplate <class T> struct hash; 110261272Sdimtemplate <class T> struct hash<optional<T>>; 111261272Sdim 112261272Sdim}} // std::experimental 113261272Sdim 114261272Sdim*/ 115261272Sdim 116261272Sdim#include <__config> 117261272Sdim#include <functional> 118261272Sdim#include <stdexcept> 119261272Sdim 120261272Sdimnamespace std { namespace experimental { 121261272Sdim 122261272Sdimclass _LIBCPP_EXCEPTION_ABI bad_optional_access 123261272Sdim : public logic_error 124261272Sdim{ 125261272Sdimpublic: 126261272Sdim#if _LIBCPP_STD_VER > 11 127261272Sdim _LIBCPP_INLINE_VISIBILITY explicit bad_optional_access(const string& __arg) 128261272Sdim : logic_error(__arg) {} 129261272Sdim _LIBCPP_INLINE_VISIBILITY explicit bad_optional_access(const char* __arg) 130261272Sdim : logic_error(__arg) {} 131261272Sdim _LIBCPP_INLINE_VISIBILITY bad_optional_access(const bad_optional_access&) noexcept = default; 132261272Sdim _LIBCPP_INLINE_VISIBILITY bad_optional_access& operator=(const bad_optional_access&) noexcept = default; 133261272Sdim#else 134261272Sdimprivate: 135261272Sdim bad_optional_access(const bad_optional_access&); 136261272Sdim bad_optional_access& operator=(const bad_optional_access&); 137261272Sdimpublic: 138261272Sdim#endif // _LIBCPP_STD_VER > 11 139261272Sdim // Get the key function ~bad_optional_access() into the dylib even if not compiling for C++1y 140261272Sdim virtual ~bad_optional_access() _NOEXCEPT; 141261272Sdim}; 142261272Sdim 143261272Sdim}} // std::experimental 144261272Sdim 145261272Sdim#if _LIBCPP_STD_VER > 11 146261272Sdim 147261272Sdim#include <initializer_list> 148261272Sdim#include <type_traits> 149261272Sdim#include <new> 150261272Sdim#include <__functional_base> 151261272Sdim 152261272Sdim#include <__undef_min_max> 153261272Sdim 154261272Sdim#ifdef _LIBCPP_DEBUG 155261272Sdim# include <__debug> 156261272Sdim#else 157261272Sdim# define _LIBCPP_ASSERT(x, m) ((void)0) 158261272Sdim#endif 159261272Sdim 160261272Sdim#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 161261272Sdim#pragma GCC system_header 162261272Sdim#endif 163261272Sdim 164261272Sdimnamespace std { namespace experimental { inline namespace __library_fundamentals_v1 { 165261272Sdim 166261272Sdimstruct in_place_t {}; 167261272Sdimconstexpr in_place_t in_place{}; 168261272Sdim 169261272Sdimstruct nullopt_t 170261272Sdim{ 171261272Sdim explicit constexpr nullopt_t(int) noexcept {} 172261272Sdim}; 173261272Sdim 174261272Sdimconstexpr nullopt_t nullopt{0}; 175261272Sdim 176261272Sdimtemplate <class _Tp, bool = is_trivially_destructible<_Tp>::value> 177261272Sdimclass __optional_storage 178261272Sdim{ 179261272Sdimprotected: 180261272Sdim typedef _Tp value_type; 181261272Sdim union 182261272Sdim { 183261272Sdim char __null_state_; 184261272Sdim value_type __val_; 185261272Sdim }; 186261272Sdim bool __engaged_ = false; 187261272Sdim 188261272Sdim _LIBCPP_INLINE_VISIBILITY 189261272Sdim ~__optional_storage() 190261272Sdim { 191261272Sdim if (__engaged_) 192261272Sdim __val_.~value_type(); 193261272Sdim } 194261272Sdim 195261272Sdim _LIBCPP_INLINE_VISIBILITY 196261272Sdim constexpr __optional_storage() noexcept 197261272Sdim : __null_state_('\0') {} 198261272Sdim 199261272Sdim _LIBCPP_INLINE_VISIBILITY 200261272Sdim __optional_storage(const __optional_storage& __x) 201261272Sdim : __engaged_(__x.__engaged_) 202261272Sdim { 203261272Sdim if (__engaged_) 204261272Sdim ::new(_VSTD::addressof(__val_)) value_type(__x.__val_); 205261272Sdim } 206261272Sdim 207261272Sdim _LIBCPP_INLINE_VISIBILITY 208261272Sdim __optional_storage(__optional_storage&& __x) 209261272Sdim noexcept(is_nothrow_move_constructible<value_type>::value) 210261272Sdim : __engaged_(__x.__engaged_) 211261272Sdim { 212261272Sdim if (__engaged_) 213261272Sdim ::new(_VSTD::addressof(__val_)) value_type(_VSTD::move(__x.__val_)); 214261272Sdim } 215261272Sdim 216261272Sdim _LIBCPP_INLINE_VISIBILITY 217261272Sdim constexpr __optional_storage(const value_type& __v) 218261272Sdim : __val_(__v), 219261272Sdim __engaged_(true) {} 220261272Sdim 221261272Sdim _LIBCPP_INLINE_VISIBILITY 222261272Sdim constexpr __optional_storage(value_type&& __v) 223261272Sdim : __val_(_VSTD::move(__v)), 224261272Sdim __engaged_(true) {} 225261272Sdim 226261272Sdim template <class... _Args> 227261272Sdim _LIBCPP_INLINE_VISIBILITY 228261272Sdim constexpr 229261272Sdim explicit __optional_storage(in_place_t, _Args&&... __args) 230261272Sdim : __val_(_VSTD::forward<_Args>(__args)...), 231261272Sdim __engaged_(true) {} 232261272Sdim}; 233261272Sdim 234261272Sdimtemplate <class _Tp> 235261272Sdimclass __optional_storage<_Tp, true> 236261272Sdim{ 237261272Sdimprotected: 238261272Sdim typedef _Tp value_type; 239261272Sdim union 240261272Sdim { 241261272Sdim char __null_state_; 242261272Sdim value_type __val_; 243261272Sdim }; 244261272Sdim bool __engaged_ = false; 245261272Sdim 246261272Sdim _LIBCPP_INLINE_VISIBILITY 247261272Sdim constexpr __optional_storage() noexcept 248261272Sdim : __null_state_('\0') {} 249261272Sdim 250261272Sdim _LIBCPP_INLINE_VISIBILITY 251261272Sdim __optional_storage(const __optional_storage& __x) 252261272Sdim : __engaged_(__x.__engaged_) 253261272Sdim { 254261272Sdim if (__engaged_) 255261272Sdim ::new(_VSTD::addressof(__val_)) value_type(__x.__val_); 256261272Sdim } 257261272Sdim 258261272Sdim _LIBCPP_INLINE_VISIBILITY 259261272Sdim __optional_storage(__optional_storage&& __x) 260261272Sdim noexcept(is_nothrow_move_constructible<value_type>::value) 261261272Sdim : __engaged_(__x.__engaged_) 262261272Sdim { 263261272Sdim if (__engaged_) 264261272Sdim ::new(_VSTD::addressof(__val_)) value_type(_VSTD::move(__x.__val_)); 265261272Sdim } 266261272Sdim 267261272Sdim _LIBCPP_INLINE_VISIBILITY 268261272Sdim constexpr __optional_storage(const value_type& __v) 269261272Sdim : __val_(__v), 270261272Sdim __engaged_(true) {} 271261272Sdim 272261272Sdim _LIBCPP_INLINE_VISIBILITY 273261272Sdim constexpr __optional_storage(value_type&& __v) 274261272Sdim : __val_(_VSTD::move(__v)), 275261272Sdim __engaged_(true) {} 276261272Sdim 277261272Sdim template <class... _Args> 278261272Sdim _LIBCPP_INLINE_VISIBILITY 279261272Sdim constexpr 280261272Sdim explicit __optional_storage(in_place_t, _Args&&... __args) 281261272Sdim : __val_(_VSTD::forward<_Args>(__args)...), 282261272Sdim __engaged_(true) {} 283261272Sdim}; 284261272Sdim 285261272Sdimtemplate <class _Tp> 286261272Sdimclass optional 287261272Sdim : private __optional_storage<_Tp> 288261272Sdim{ 289261272Sdim typedef __optional_storage<_Tp> __base; 290261272Sdimpublic: 291261272Sdim typedef _Tp value_type; 292261272Sdim 293261272Sdim static_assert(!is_reference<value_type>::value, 294261272Sdim "Instantiation of optional with a reference type is ill-formed."); 295261272Sdim static_assert(!is_same<typename remove_cv<value_type>::type, in_place_t>::value, 296261272Sdim "Instantiation of optional with a in_place_t type is ill-formed."); 297261272Sdim static_assert(!is_same<typename remove_cv<value_type>::type, nullopt_t>::value, 298261272Sdim "Instantiation of optional with a nullopt_t type is ill-formed."); 299261272Sdim static_assert(is_object<value_type>::value, 300261272Sdim "Instantiation of optional with a non-object type is undefined behavior."); 301261272Sdim static_assert(is_nothrow_destructible<value_type>::value, 302261272Sdim "Instantiation of optional with an object type that is not noexcept destructible is undefined behavior."); 303261272Sdim 304261272Sdim _LIBCPP_INLINE_VISIBILITY constexpr optional() noexcept {} 305261272Sdim _LIBCPP_INLINE_VISIBILITY optional(const optional&) = default; 306261272Sdim _LIBCPP_INLINE_VISIBILITY optional(optional&&) = default; 307261272Sdim _LIBCPP_INLINE_VISIBILITY ~optional() = default; 308261272Sdim _LIBCPP_INLINE_VISIBILITY constexpr optional(nullopt_t) noexcept {} 309261272Sdim _LIBCPP_INLINE_VISIBILITY constexpr optional(const value_type& __v) 310261272Sdim : __base(__v) {} 311261272Sdim _LIBCPP_INLINE_VISIBILITY constexpr optional(value_type&& __v) 312261272Sdim : __base(_VSTD::move(__v)) {} 313261272Sdim 314261272Sdim template <class... _Args, 315261272Sdim class = typename enable_if 316261272Sdim < 317261272Sdim is_constructible<value_type, _Args...>::value 318261272Sdim >::type 319261272Sdim > 320261272Sdim _LIBCPP_INLINE_VISIBILITY 321261272Sdim constexpr 322261272Sdim explicit optional(in_place_t, _Args&&... __args) 323261272Sdim : __base(in_place, _VSTD::forward<_Args>(__args)...) {} 324261272Sdim 325261272Sdim template <class _Up, class... _Args, 326261272Sdim class = typename enable_if 327261272Sdim < 328261272Sdim is_constructible<value_type, initializer_list<_Up>&, _Args...>::value 329261272Sdim >::type 330261272Sdim > 331261272Sdim _LIBCPP_INLINE_VISIBILITY 332261272Sdim constexpr 333261272Sdim explicit optional(in_place_t, initializer_list<_Up> __il, _Args&&... __args) 334261272Sdim : __base(in_place, __il, _VSTD::forward<_Args>(__args)...) {} 335261272Sdim 336261272Sdim _LIBCPP_INLINE_VISIBILITY 337261272Sdim optional& operator=(nullopt_t) noexcept 338261272Sdim { 339261272Sdim if (this->__engaged_) 340261272Sdim { 341261272Sdim this->__val_.~value_type(); 342261272Sdim this->__engaged_ = false; 343261272Sdim } 344261272Sdim return *this; 345261272Sdim } 346261272Sdim 347261272Sdim _LIBCPP_INLINE_VISIBILITY 348261272Sdim optional& 349261272Sdim operator=(const optional& __opt) 350261272Sdim { 351261272Sdim if (this->__engaged_ == __opt.__engaged_) 352261272Sdim { 353261272Sdim if (this->__engaged_) 354261272Sdim this->__val_ = __opt.__val_; 355261272Sdim } 356261272Sdim else 357261272Sdim { 358261272Sdim if (this->__engaged_) 359261272Sdim this->__val_.~value_type(); 360261272Sdim else 361261272Sdim ::new(_VSTD::addressof(this->__val_)) value_type(__opt.__val_); 362261272Sdim this->__engaged_ = __opt.__engaged_; 363261272Sdim } 364261272Sdim return *this; 365261272Sdim } 366261272Sdim 367261272Sdim _LIBCPP_INLINE_VISIBILITY 368261272Sdim optional& 369261272Sdim operator=(optional&& __opt) 370261272Sdim noexcept(is_nothrow_move_assignable<value_type>::value && 371261272Sdim is_nothrow_move_constructible<value_type>::value) 372261272Sdim { 373261272Sdim if (this->__engaged_ == __opt.__engaged_) 374261272Sdim { 375261272Sdim if (this->__engaged_) 376261272Sdim this->__val_ = _VSTD::move(__opt.__val_); 377261272Sdim } 378261272Sdim else 379261272Sdim { 380261272Sdim if (this->__engaged_) 381261272Sdim this->__val_.~value_type(); 382261272Sdim else 383261272Sdim ::new(_VSTD::addressof(this->__val_)) value_type(_VSTD::move(__opt.__val_)); 384261272Sdim this->__engaged_ = __opt.__engaged_; 385261272Sdim } 386261272Sdim return *this; 387261272Sdim } 388261272Sdim 389261272Sdim template <class _Up, 390261272Sdim class = typename enable_if 391261272Sdim < 392261272Sdim is_same<typename remove_reference<_Up>::type, value_type>::value && 393261272Sdim is_constructible<value_type, _Up>::value && 394261272Sdim is_assignable<value_type&, _Up>::value 395261272Sdim >::type 396261272Sdim > 397261272Sdim _LIBCPP_INLINE_VISIBILITY 398261272Sdim optional& 399261272Sdim operator=(_Up&& __v) 400261272Sdim { 401261272Sdim if (this->__engaged_) 402261272Sdim this->__val_ = _VSTD::forward<_Up>(__v); 403261272Sdim else 404261272Sdim { 405261272Sdim ::new(_VSTD::addressof(this->__val_)) value_type(_VSTD::forward<_Up>(__v)); 406261272Sdim this->__engaged_ = true; 407261272Sdim } 408261272Sdim return *this; 409261272Sdim } 410261272Sdim 411261272Sdim template <class... _Args, 412261272Sdim class = typename enable_if 413261272Sdim < 414261272Sdim is_constructible<value_type, _Args...>::value 415261272Sdim >::type 416261272Sdim > 417261272Sdim _LIBCPP_INLINE_VISIBILITY 418261272Sdim void 419261272Sdim emplace(_Args&&... __args) 420261272Sdim { 421261272Sdim *this = nullopt; 422261272Sdim ::new(_VSTD::addressof(this->__val_)) value_type(_VSTD::forward<_Args>(__args)...); 423261272Sdim this->__engaged_ = true; 424261272Sdim } 425261272Sdim 426261272Sdim template <class _Up, class... _Args, 427261272Sdim class = typename enable_if 428261272Sdim < 429261272Sdim is_constructible<value_type, initializer_list<_Up>&, _Args...>::value 430261272Sdim >::type 431261272Sdim > 432261272Sdim _LIBCPP_INLINE_VISIBILITY 433261272Sdim void 434261272Sdim emplace(initializer_list<_Up> __il, _Args&&... __args) 435261272Sdim { 436261272Sdim *this = nullopt; 437261272Sdim ::new(_VSTD::addressof(this->__val_)) value_type(__il, _VSTD::forward<_Args>(__args)...); 438261272Sdim this->__engaged_ = true; 439261272Sdim } 440261272Sdim 441261272Sdim _LIBCPP_INLINE_VISIBILITY 442261272Sdim void 443261272Sdim swap(optional& __opt) 444261272Sdim noexcept(is_nothrow_move_constructible<value_type>::value && 445261272Sdim __is_nothrow_swappable<value_type>::value) 446261272Sdim { 447261272Sdim using _VSTD::swap; 448261272Sdim if (this->__engaged_ == __opt.__engaged_) 449261272Sdim { 450261272Sdim if (this->__engaged_) 451261272Sdim swap(this->__val_, __opt.__val_); 452261272Sdim } 453261272Sdim else 454261272Sdim { 455261272Sdim if (this->__engaged_) 456261272Sdim { 457261272Sdim ::new(_VSTD::addressof(__opt.__val_)) value_type(_VSTD::move(this->__val_)); 458261272Sdim this->__val_.~value_type(); 459261272Sdim } 460261272Sdim else 461261272Sdim { 462261272Sdim ::new(_VSTD::addressof(this->__val_)) value_type(_VSTD::move(__opt.__val_)); 463261272Sdim __opt.__val_.~value_type(); 464261272Sdim } 465261272Sdim swap(this->__engaged_, __opt.__engaged_); 466261272Sdim } 467261272Sdim } 468261272Sdim 469261272Sdim _LIBCPP_INLINE_VISIBILITY 470261272Sdim constexpr 471261272Sdim value_type const* 472261272Sdim operator->() const 473261272Sdim { 474261272Sdim _LIBCPP_ASSERT(this->__engaged_, "optional operator-> called for disengaged value"); 475261272Sdim return __operator_arrow(__has_operator_addressof<value_type>{}); 476261272Sdim } 477261272Sdim 478261272Sdim _LIBCPP_INLINE_VISIBILITY 479261272Sdim value_type* 480261272Sdim operator->() 481261272Sdim { 482261272Sdim _LIBCPP_ASSERT(this->__engaged_, "optional operator-> called for disengaged value"); 483261272Sdim return _VSTD::addressof(this->__val_); 484261272Sdim } 485261272Sdim 486261272Sdim _LIBCPP_INLINE_VISIBILITY 487261272Sdim constexpr 488261272Sdim const value_type& 489261272Sdim operator*() const 490261272Sdim { 491261272Sdim _LIBCPP_ASSERT(this->__engaged_, "optional operator* called for disengaged value"); 492261272Sdim return this->__val_; 493261272Sdim } 494261272Sdim 495261272Sdim _LIBCPP_INLINE_VISIBILITY 496261272Sdim value_type& 497261272Sdim operator*() 498261272Sdim { 499261272Sdim _LIBCPP_ASSERT(this->__engaged_, "optional operator* called for disengaged value"); 500261272Sdim return this->__val_; 501261272Sdim } 502261272Sdim 503261272Sdim _LIBCPP_INLINE_VISIBILITY 504261272Sdim constexpr explicit operator bool() const noexcept {return this->__engaged_;} 505261272Sdim 506261272Sdim _LIBCPP_INLINE_VISIBILITY 507261272Sdim constexpr value_type const& value() const 508261272Sdim { 509261272Sdim if (!this->__engaged_) 510261272Sdim throw bad_optional_access("optional<T>::value: not engaged"); 511261272Sdim return this->__val_; 512261272Sdim } 513261272Sdim 514261272Sdim _LIBCPP_INLINE_VISIBILITY 515261272Sdim value_type& value() 516261272Sdim { 517261272Sdim if (!this->__engaged_) 518261272Sdim throw bad_optional_access("optional<T>::value: not engaged"); 519261272Sdim return this->__val_; 520261272Sdim } 521261272Sdim 522261272Sdim template <class _Up> 523261272Sdim _LIBCPP_INLINE_VISIBILITY 524261272Sdim constexpr value_type value_or(_Up&& __v) const& 525261272Sdim { 526261272Sdim static_assert(is_copy_constructible<value_type>::value, 527261272Sdim "optional<T>::value_or: T must be copy constructible"); 528261272Sdim static_assert(is_convertible<_Up, value_type>::value, 529261272Sdim "optional<T>::value_or: U must be convertible to T"); 530261272Sdim return this->__engaged_ ? this->__val_ : 531261272Sdim static_cast<value_type>(_VSTD::forward<_Up>(__v)); 532261272Sdim } 533261272Sdim 534261272Sdim template <class _Up> 535261272Sdim _LIBCPP_INLINE_VISIBILITY 536261272Sdim value_type value_or(_Up&& __v) && 537261272Sdim { 538261272Sdim static_assert(is_move_constructible<value_type>::value, 539261272Sdim "optional<T>::value_or: T must be move constructible"); 540261272Sdim static_assert(is_convertible<_Up, value_type>::value, 541261272Sdim "optional<T>::value_or: U must be convertible to T"); 542261272Sdim return this->__engaged_ ? _VSTD::move(this->__val_) : 543261272Sdim static_cast<value_type>(_VSTD::forward<_Up>(__v)); 544261272Sdim } 545261272Sdim 546261272Sdimprivate: 547261272Sdim _LIBCPP_INLINE_VISIBILITY 548261272Sdim value_type const* 549261272Sdim __operator_arrow(true_type) const 550261272Sdim { 551261272Sdim return _VSTD::addressof(this->__val_); 552261272Sdim } 553261272Sdim 554261272Sdim _LIBCPP_INLINE_VISIBILITY 555261272Sdim constexpr 556261272Sdim value_type const* 557261272Sdim __operator_arrow(false_type) const 558261272Sdim { 559261272Sdim return &this->__val_; 560261272Sdim } 561261272Sdim}; 562261272Sdim 563261272Sdimtemplate <class _Tp> 564261272Sdiminline _LIBCPP_INLINE_VISIBILITY 565261272Sdimconstexpr 566261272Sdimbool 567261272Sdimoperator==(const optional<_Tp>& __x, const optional<_Tp>& __y) 568261272Sdim{ 569261272Sdim if (static_cast<bool>(__x) != static_cast<bool>(__y)) 570261272Sdim return false; 571261272Sdim if (!static_cast<bool>(__x)) 572261272Sdim return true; 573261272Sdim return *__x == *__y; 574261272Sdim} 575261272Sdim 576261272Sdimtemplate <class _Tp> 577261272Sdiminline _LIBCPP_INLINE_VISIBILITY 578261272Sdimconstexpr 579261272Sdimbool 580261272Sdimoperator<(const optional<_Tp>& __x, const optional<_Tp>& __y) 581261272Sdim{ 582261272Sdim if (!static_cast<bool>(__y)) 583261272Sdim return false; 584261272Sdim if (!static_cast<bool>(__x)) 585261272Sdim return true; 586261272Sdim return less<_Tp>{}(*__x, *__y); 587261272Sdim} 588261272Sdim 589261272Sdimtemplate <class _Tp> 590261272Sdiminline _LIBCPP_INLINE_VISIBILITY 591261272Sdimconstexpr 592261272Sdimbool 593261272Sdimoperator==(const optional<_Tp>& __x, nullopt_t) noexcept 594261272Sdim{ 595261272Sdim return !static_cast<bool>(__x); 596261272Sdim} 597261272Sdim 598261272Sdimtemplate <class _Tp> 599261272Sdiminline _LIBCPP_INLINE_VISIBILITY 600261272Sdimconstexpr 601261272Sdimbool 602261272Sdimoperator==(nullopt_t, const optional<_Tp>& __x) noexcept 603261272Sdim{ 604261272Sdim return !static_cast<bool>(__x); 605261272Sdim} 606261272Sdim 607261272Sdimtemplate <class _Tp> 608261272Sdiminline _LIBCPP_INLINE_VISIBILITY 609261272Sdimconstexpr 610261272Sdimbool 611261272Sdimoperator<(const optional<_Tp>&, nullopt_t) noexcept 612261272Sdim{ 613261272Sdim return false; 614261272Sdim} 615261272Sdim 616261272Sdimtemplate <class _Tp> 617261272Sdiminline _LIBCPP_INLINE_VISIBILITY 618261272Sdimconstexpr 619261272Sdimbool 620261272Sdimoperator<(nullopt_t, const optional<_Tp>& __x) noexcept 621261272Sdim{ 622261272Sdim return static_cast<bool>(__x); 623261272Sdim} 624261272Sdim 625261272Sdimtemplate <class _Tp> 626261272Sdiminline _LIBCPP_INLINE_VISIBILITY 627261272Sdimconstexpr 628261272Sdimbool 629261272Sdimoperator==(const optional<_Tp>& __x, const _Tp& __v) 630261272Sdim{ 631261272Sdim return static_cast<bool>(__x) ? *__x == __v : false; 632261272Sdim} 633261272Sdim 634261272Sdimtemplate <class _Tp> 635261272Sdiminline _LIBCPP_INLINE_VISIBILITY 636261272Sdimconstexpr 637261272Sdimbool 638261272Sdimoperator==(const _Tp& __v, const optional<_Tp>& __x) 639261272Sdim{ 640261272Sdim return static_cast<bool>(__x) ? *__x == __v : false; 641261272Sdim} 642261272Sdim 643261272Sdimtemplate <class _Tp> 644261272Sdiminline _LIBCPP_INLINE_VISIBILITY 645261272Sdimconstexpr 646261272Sdimbool 647261272Sdimoperator<(const optional<_Tp>& __x, const _Tp& __v) 648261272Sdim{ 649261272Sdim return static_cast<bool>(__x) ? less<_Tp>{}(*__x, __v) : true; 650261272Sdim} 651261272Sdim 652261272Sdimtemplate <class _Tp> 653261272Sdiminline _LIBCPP_INLINE_VISIBILITY 654261272Sdimconstexpr 655261272Sdimbool 656261272Sdimoperator<(const _Tp& __v, const optional<_Tp>& __x) 657261272Sdim{ 658261272Sdim return static_cast<bool>(__x) ? less<_Tp>{}(__v, *__x) : false; 659261272Sdim} 660261272Sdim 661261272Sdimtemplate <class _Tp> 662261272Sdiminline _LIBCPP_INLINE_VISIBILITY 663261272Sdimvoid 664261272Sdimswap(optional<_Tp>& __x, optional<_Tp>& __y) noexcept(noexcept(__x.swap(__y))) 665261272Sdim{ 666261272Sdim __x.swap(__y); 667261272Sdim} 668261272Sdim 669261272Sdimtemplate <class _Tp> 670261272Sdiminline _LIBCPP_INLINE_VISIBILITY 671261272Sdimconstexpr 672261272Sdimoptional<typename decay<_Tp>::type> 673261272Sdimmake_optional(_Tp&& __v) 674261272Sdim{ 675261272Sdim return optional<typename decay<_Tp>::type>(_VSTD::forward<_Tp>(__v)); 676261272Sdim} 677261272Sdim 678261272Sdim}}} // namespace std::experimental::__library_fundamentals_v1 679261272Sdim 680261272Sdim_LIBCPP_BEGIN_NAMESPACE_STD 681261272Sdim 682261272Sdimtemplate <class _Tp> 683261272Sdimstruct _LIBCPP_TYPE_VIS_ONLY hash<std::experimental::optional<_Tp> > 684261272Sdim{ 685261272Sdim typedef std::experimental::optional<_Tp> argument_type; 686261272Sdim typedef size_t result_type; 687261272Sdim 688261272Sdim _LIBCPP_INLINE_VISIBILITY 689261272Sdim result_type operator()(const argument_type& __opt) const _NOEXCEPT 690261272Sdim { 691261272Sdim return static_cast<bool>(__opt) ? hash<_Tp>()(*__opt) : 0; 692261272Sdim } 693261272Sdim}; 694261272Sdim 695261272Sdim_LIBCPP_END_NAMESPACE_STD 696261272Sdim 697261272Sdim#endif // _LIBCPP_STD_VER > 11 698261272Sdim 699261272Sdim#endif // _LIBCPP_ARRAY 700