1aed8d94eSDimitry Andric// -*- C++ -*- 2aed8d94eSDimitry Andric//===-------------------------- optional ----------------------------------===// 3aed8d94eSDimitry Andric// 4aed8d94eSDimitry Andric// The LLVM Compiler Infrastructure 5aed8d94eSDimitry Andric// 6aed8d94eSDimitry Andric// This file is dual licensed under the MIT and the University of Illinois Open 7aed8d94eSDimitry Andric// Source Licenses. See LICENSE.TXT for details. 8aed8d94eSDimitry Andric// 9aed8d94eSDimitry Andric//===----------------------------------------------------------------------===// 10aed8d94eSDimitry Andric 11aed8d94eSDimitry Andric#ifndef _LIBCPP_OPTIONAL 12aed8d94eSDimitry Andric#define _LIBCPP_OPTIONAL 13aed8d94eSDimitry Andric 14aed8d94eSDimitry Andric/* 15aed8d94eSDimitry Andric optional synopsis 16aed8d94eSDimitry Andric 17aed8d94eSDimitry Andric// C++1z 18aed8d94eSDimitry Andric 19aed8d94eSDimitry Andricnamespace std { 20540d2a8bSDimitry Andric // 23.6.3, optional for object types 21aed8d94eSDimitry Andric template <class T> class optional; 22aed8d94eSDimitry Andric 23540d2a8bSDimitry Andric // 23.6.4, no-value state indicator 24aed8d94eSDimitry Andric struct nullopt_t{see below }; 2530785c0eSDimitry Andric inline constexpr nullopt_t nullopt(unspecified ); 26aed8d94eSDimitry Andric 27540d2a8bSDimitry Andric // 23.6.5, class bad_optional_access 28aed8d94eSDimitry Andric class bad_optional_access; 29aed8d94eSDimitry Andric 30540d2a8bSDimitry Andric // 23.6.6, relational operators 31540d2a8bSDimitry Andric template <class T, class U> 32540d2a8bSDimitry Andric constexpr bool operator==(const optional<T>&, const optional<U>&); 33540d2a8bSDimitry Andric template <class T, class U> 34540d2a8bSDimitry Andric constexpr bool operator!=(const optional<T>&, const optional<U>&); 35540d2a8bSDimitry Andric template <class T, class U> 36540d2a8bSDimitry Andric constexpr bool operator<(const optional<T>&, const optional<U>&); 37540d2a8bSDimitry Andric template <class T, class U> 38540d2a8bSDimitry Andric constexpr bool operator>(const optional<T>&, const optional<U>&); 39540d2a8bSDimitry Andric template <class T, class U> 40540d2a8bSDimitry Andric constexpr bool operator<=(const optional<T>&, const optional<U>&); 41540d2a8bSDimitry Andric template <class T, class U> 42540d2a8bSDimitry Andric constexpr bool operator>=(const optional<T>&, const optional<U>&); 43540d2a8bSDimitry Andric 44540d2a8bSDimitry Andric // 23.6.7 comparison with nullopt 45aed8d94eSDimitry Andric template <class T> constexpr bool operator==(const optional<T>&, nullopt_t) noexcept; 46aed8d94eSDimitry Andric template <class T> constexpr bool operator==(nullopt_t, const optional<T>&) noexcept; 47aed8d94eSDimitry Andric template <class T> constexpr bool operator!=(const optional<T>&, nullopt_t) noexcept; 48aed8d94eSDimitry Andric template <class T> constexpr bool operator!=(nullopt_t, const optional<T>&) noexcept; 49aed8d94eSDimitry Andric template <class T> constexpr bool operator<(const optional<T>&, nullopt_t) noexcept; 50aed8d94eSDimitry Andric template <class T> constexpr bool operator<(nullopt_t, const optional<T>&) noexcept; 51aed8d94eSDimitry Andric template <class T> constexpr bool operator<=(const optional<T>&, nullopt_t) noexcept; 52aed8d94eSDimitry Andric template <class T> constexpr bool operator<=(nullopt_t, const optional<T>&) noexcept; 53aed8d94eSDimitry Andric template <class T> constexpr bool operator>(const optional<T>&, nullopt_t) noexcept; 54aed8d94eSDimitry Andric template <class T> constexpr bool operator>(nullopt_t, const optional<T>&) noexcept; 55aed8d94eSDimitry Andric template <class T> constexpr bool operator>=(const optional<T>&, nullopt_t) noexcept; 56aed8d94eSDimitry Andric template <class T> constexpr bool operator>=(nullopt_t, const optional<T>&) noexcept; 57aed8d94eSDimitry Andric 58540d2a8bSDimitry Andric // 23.6.8, comparison with T 59540d2a8bSDimitry Andric template <class T, class U> constexpr bool operator==(const optional<T>&, const U&); 60b2c7081bSDimitry Andric template <class T, class U> constexpr bool operator==(const T&, const optional<U>&); 61540d2a8bSDimitry Andric template <class T, class U> constexpr bool operator!=(const optional<T>&, const U&); 62b2c7081bSDimitry Andric template <class T, class U> constexpr bool operator!=(const T&, const optional<U>&); 63540d2a8bSDimitry Andric template <class T, class U> constexpr bool operator<(const optional<T>&, const U&); 64b2c7081bSDimitry Andric template <class T, class U> constexpr bool operator<(const T&, const optional<U>&); 65540d2a8bSDimitry Andric template <class T, class U> constexpr bool operator<=(const optional<T>&, const U&); 66b2c7081bSDimitry Andric template <class T, class U> constexpr bool operator<=(const T&, const optional<U>&); 67540d2a8bSDimitry Andric template <class T, class U> constexpr bool operator>(const optional<T>&, const U&); 68b2c7081bSDimitry Andric template <class T, class U> constexpr bool operator>(const T&, const optional<U>&); 69540d2a8bSDimitry Andric template <class T, class U> constexpr bool operator>=(const optional<T>&, const U&); 70b2c7081bSDimitry Andric template <class T, class U> constexpr bool operator>=(const T&, const optional<U>&); 71aed8d94eSDimitry Andric 72540d2a8bSDimitry Andric // 23.6.9, specialized algorithms 73aed8d94eSDimitry Andric template <class T> void swap(optional<T>&, optional<T>&) noexcept(see below ); 74aed8d94eSDimitry Andric template <class T> constexpr optional<see below > make_optional(T&&); 75aed8d94eSDimitry Andric template <class T, class... Args> 76aed8d94eSDimitry Andric constexpr optional<T> make_optional(Args&&... args); 77aed8d94eSDimitry Andric template <class T, class U, class... Args> 78aed8d94eSDimitry Andric constexpr optional<T> make_optional(initializer_list<U> il, Args&&... args); 79aed8d94eSDimitry Andric 80540d2a8bSDimitry Andric // 23.6.10, hash support 81aed8d94eSDimitry Andric template <class T> struct hash; 82aed8d94eSDimitry Andric template <class T> struct hash<optional<T>>; 83aed8d94eSDimitry Andric 84aed8d94eSDimitry Andric template <class T> class optional { 85aed8d94eSDimitry Andric public: 86aed8d94eSDimitry Andric using value_type = T; 87aed8d94eSDimitry Andric 88540d2a8bSDimitry Andric // 23.6.3.1, constructors 89aed8d94eSDimitry Andric constexpr optional() noexcept; 90aed8d94eSDimitry Andric constexpr optional(nullopt_t) noexcept; 91aed8d94eSDimitry Andric optional(const optional &); 92aed8d94eSDimitry Andric optional(optional &&) noexcept(see below); 93aed8d94eSDimitry Andric template <class... Args> constexpr explicit optional(in_place_t, Args &&...); 94aed8d94eSDimitry Andric template <class U, class... Args> 95aed8d94eSDimitry Andric constexpr explicit optional(in_place_t, initializer_list<U>, Args &&...); 96aed8d94eSDimitry Andric template <class U = T> 97aed8d94eSDimitry Andric constexpr EXPLICIT optional(U &&); 98aed8d94eSDimitry Andric template <class U> 99aed8d94eSDimitry Andric constexpr EXPLICIT optional(const optional<U> &); 100aed8d94eSDimitry Andric template <class U> 101aed8d94eSDimitry Andric constexpr EXPLICIT optional(optional<U> &&); 102aed8d94eSDimitry Andric 103540d2a8bSDimitry Andric // 23.6.3.2, destructor 104aed8d94eSDimitry Andric ~optional(); 105aed8d94eSDimitry Andric 106540d2a8bSDimitry Andric // 23.6.3.3, assignment 107aed8d94eSDimitry Andric optional &operator=(nullopt_t) noexcept; 108*b5893f02SDimitry Andric optional &operator=(const optional &); // constexpr in C++20 109*b5893f02SDimitry Andric optional &operator=(optional &&) noexcept(see below); // constexpr in C++20 110aed8d94eSDimitry Andric template <class U = T> optional &operator=(U &&); 111aed8d94eSDimitry Andric template <class U> optional &operator=(const optional<U> &); 112aed8d94eSDimitry Andric template <class U> optional &operator=(optional<U> &&); 113540d2a8bSDimitry Andric template <class... Args> T& emplace(Args &&...); 114aed8d94eSDimitry Andric template <class U, class... Args> 115540d2a8bSDimitry Andric T& emplace(initializer_list<U>, Args &&...); 116aed8d94eSDimitry Andric 117540d2a8bSDimitry Andric // 23.6.3.4, swap 118aed8d94eSDimitry Andric void swap(optional &) noexcept(see below ); 119aed8d94eSDimitry Andric 120540d2a8bSDimitry Andric // 23.6.3.5, observers 121aed8d94eSDimitry Andric constexpr T const *operator->() const; 122aed8d94eSDimitry Andric constexpr T *operator->(); 123aed8d94eSDimitry Andric constexpr T const &operator*() const &; 124aed8d94eSDimitry Andric constexpr T &operator*() &; 125aed8d94eSDimitry Andric constexpr T &&operator*() &&; 126aed8d94eSDimitry Andric constexpr const T &&operator*() const &&; 127aed8d94eSDimitry Andric constexpr explicit operator bool() const noexcept; 128aed8d94eSDimitry Andric constexpr bool has_value() const noexcept; 129aed8d94eSDimitry Andric constexpr T const &value() const &; 130aed8d94eSDimitry Andric constexpr T &value() &; 131aed8d94eSDimitry Andric constexpr T &&value() &&; 132aed8d94eSDimitry Andric constexpr const T &&value() const &&; 133aed8d94eSDimitry Andric template <class U> constexpr T value_or(U &&) const &; 134aed8d94eSDimitry Andric template <class U> constexpr T value_or(U &&) &&; 135aed8d94eSDimitry Andric 136540d2a8bSDimitry Andric // 23.6.3.6, modifiers 137aed8d94eSDimitry Andric void reset() noexcept; 138aed8d94eSDimitry Andric 139aed8d94eSDimitry Andric private: 140aed8d94eSDimitry Andric T *val; // exposition only 141aed8d94eSDimitry Andric }; 1424ba319b5SDimitry Andric 1434ba319b5SDimitry Andrictemplate<class T> 1444ba319b5SDimitry Andric optional(T) -> optional<T>; 1454ba319b5SDimitry Andric 146aed8d94eSDimitry Andric} // namespace std 147aed8d94eSDimitry Andric 148aed8d94eSDimitry Andric*/ 149aed8d94eSDimitry Andric 150aed8d94eSDimitry Andric#include <__config> 151aed8d94eSDimitry Andric#include <__debug> 152aed8d94eSDimitry Andric#include <__functional_base> 153aed8d94eSDimitry Andric#include <functional> 154aed8d94eSDimitry Andric#include <initializer_list> 155aed8d94eSDimitry Andric#include <new> 156aed8d94eSDimitry Andric#include <stdexcept> 157aed8d94eSDimitry Andric#include <type_traits> 158aed8d94eSDimitry Andric#include <utility> 159*b5893f02SDimitry Andric#include <version> 160aed8d94eSDimitry Andric 161aed8d94eSDimitry Andric#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 162aed8d94eSDimitry Andric#pragma GCC system_header 163aed8d94eSDimitry Andric#endif 164aed8d94eSDimitry Andric 165f9448bf3SDimitry Andric_LIBCPP_PUSH_MACROS 166f9448bf3SDimitry Andric#include <__undef_macros> 167f9448bf3SDimitry Andric 168f9448bf3SDimitry Andric 169aed8d94eSDimitry Andricnamespace std // purposefully not using versioning namespace 170aed8d94eSDimitry Andric{ 171aed8d94eSDimitry Andric 172*b5893f02SDimitry Andricclass _LIBCPP_EXCEPTION_ABI _LIBCPP_AVAILABILITY_BAD_OPTIONAL_ACCESS bad_optional_access 1735ca5951eSDimitry Andric : public exception 174aed8d94eSDimitry Andric{ 175aed8d94eSDimitry Andricpublic: 176aed8d94eSDimitry Andric // Get the key function ~bad_optional_access() into the dylib 177aed8d94eSDimitry Andric virtual ~bad_optional_access() _NOEXCEPT; 1785ca5951eSDimitry Andric virtual const char* what() const _NOEXCEPT; 179aed8d94eSDimitry Andric}; 180aed8d94eSDimitry Andric 181aed8d94eSDimitry Andric} // std 182aed8d94eSDimitry Andric 183aed8d94eSDimitry Andric#if _LIBCPP_STD_VER > 14 184aed8d94eSDimitry Andric 185aed8d94eSDimitry Andric_LIBCPP_BEGIN_NAMESPACE_STD 186aed8d94eSDimitry Andric 187aed8d94eSDimitry Andric_LIBCPP_NORETURN 188aed8d94eSDimitry Andricinline _LIBCPP_INLINE_VISIBILITY 189*b5893f02SDimitry Andric_LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS 190aed8d94eSDimitry Andricvoid __throw_bad_optional_access() { 191aed8d94eSDimitry Andric#ifndef _LIBCPP_NO_EXCEPTIONS 192aed8d94eSDimitry Andric throw bad_optional_access(); 193aed8d94eSDimitry Andric#else 194aed8d94eSDimitry Andric _VSTD::abort(); 195aed8d94eSDimitry Andric#endif 196aed8d94eSDimitry Andric} 197aed8d94eSDimitry Andric 198aed8d94eSDimitry Andricstruct nullopt_t 199aed8d94eSDimitry Andric{ 200aed8d94eSDimitry Andric struct __secret_tag { _LIBCPP_INLINE_VISIBILITY explicit __secret_tag() = default; }; 201aed8d94eSDimitry Andric _LIBCPP_INLINE_VISIBILITY constexpr explicit nullopt_t(__secret_tag, __secret_tag) noexcept {} 202aed8d94eSDimitry Andric}; 203aed8d94eSDimitry Andric 20430785c0eSDimitry Andric_LIBCPP_INLINE_VAR constexpr nullopt_t nullopt{nullopt_t::__secret_tag{}, nullopt_t::__secret_tag{}}; 205aed8d94eSDimitry Andric 206aed8d94eSDimitry Andrictemplate <class _Tp, bool = is_trivially_destructible<_Tp>::value> 207aed8d94eSDimitry Andricstruct __optional_destruct_base; 208aed8d94eSDimitry Andric 209aed8d94eSDimitry Andrictemplate <class _Tp> 210aed8d94eSDimitry Andricstruct __optional_destruct_base<_Tp, false> 211aed8d94eSDimitry Andric{ 212aed8d94eSDimitry Andric typedef _Tp value_type; 213aed8d94eSDimitry Andric static_assert(is_object_v<value_type>, 214aed8d94eSDimitry Andric "instantiation of optional with a non-object type is undefined behavior"); 215aed8d94eSDimitry Andric union 216aed8d94eSDimitry Andric { 217aed8d94eSDimitry Andric char __null_state_; 218aed8d94eSDimitry Andric value_type __val_; 219aed8d94eSDimitry Andric }; 220aed8d94eSDimitry Andric bool __engaged_; 221aed8d94eSDimitry Andric 222aed8d94eSDimitry Andric _LIBCPP_INLINE_VISIBILITY 223aed8d94eSDimitry Andric ~__optional_destruct_base() 224aed8d94eSDimitry Andric { 225aed8d94eSDimitry Andric if (__engaged_) 226aed8d94eSDimitry Andric __val_.~value_type(); 227aed8d94eSDimitry Andric } 228aed8d94eSDimitry Andric 229aed8d94eSDimitry Andric _LIBCPP_INLINE_VISIBILITY 230aed8d94eSDimitry Andric constexpr __optional_destruct_base() noexcept 231aed8d94eSDimitry Andric : __null_state_(), 232aed8d94eSDimitry Andric __engaged_(false) {} 233aed8d94eSDimitry Andric 234aed8d94eSDimitry Andric template <class... _Args> 235aed8d94eSDimitry Andric _LIBCPP_INLINE_VISIBILITY 236aed8d94eSDimitry Andric constexpr explicit __optional_destruct_base(in_place_t, _Args&&... __args) 237aed8d94eSDimitry Andric : __val_(_VSTD::forward<_Args>(__args)...), 238aed8d94eSDimitry Andric __engaged_(true) {} 239aed8d94eSDimitry Andric 240aed8d94eSDimitry Andric _LIBCPP_INLINE_VISIBILITY 241aed8d94eSDimitry Andric void reset() noexcept 242aed8d94eSDimitry Andric { 243aed8d94eSDimitry Andric if (__engaged_) 244aed8d94eSDimitry Andric { 245aed8d94eSDimitry Andric __val_.~value_type(); 246aed8d94eSDimitry Andric __engaged_ = false; 247aed8d94eSDimitry Andric } 248aed8d94eSDimitry Andric } 249aed8d94eSDimitry Andric}; 250aed8d94eSDimitry Andric 251aed8d94eSDimitry Andrictemplate <class _Tp> 252aed8d94eSDimitry Andricstruct __optional_destruct_base<_Tp, true> 253aed8d94eSDimitry Andric{ 254aed8d94eSDimitry Andric typedef _Tp value_type; 255aed8d94eSDimitry Andric static_assert(is_object_v<value_type>, 256aed8d94eSDimitry Andric "instantiation of optional with a non-object type is undefined behavior"); 257aed8d94eSDimitry Andric union 258aed8d94eSDimitry Andric { 259aed8d94eSDimitry Andric char __null_state_; 260aed8d94eSDimitry Andric value_type __val_; 261aed8d94eSDimitry Andric }; 262aed8d94eSDimitry Andric bool __engaged_; 263aed8d94eSDimitry Andric 264aed8d94eSDimitry Andric _LIBCPP_INLINE_VISIBILITY 265aed8d94eSDimitry Andric constexpr __optional_destruct_base() noexcept 266aed8d94eSDimitry Andric : __null_state_(), 267aed8d94eSDimitry Andric __engaged_(false) {} 268aed8d94eSDimitry Andric 269aed8d94eSDimitry Andric template <class... _Args> 270aed8d94eSDimitry Andric _LIBCPP_INLINE_VISIBILITY 271aed8d94eSDimitry Andric constexpr explicit __optional_destruct_base(in_place_t, _Args&&... __args) 272aed8d94eSDimitry Andric : __val_(_VSTD::forward<_Args>(__args)...), 273aed8d94eSDimitry Andric __engaged_(true) {} 274aed8d94eSDimitry Andric 275aed8d94eSDimitry Andric _LIBCPP_INLINE_VISIBILITY 276aed8d94eSDimitry Andric void reset() noexcept 277aed8d94eSDimitry Andric { 278aed8d94eSDimitry Andric if (__engaged_) 279aed8d94eSDimitry Andric { 280aed8d94eSDimitry Andric __engaged_ = false; 281aed8d94eSDimitry Andric } 282aed8d94eSDimitry Andric } 283aed8d94eSDimitry Andric}; 284aed8d94eSDimitry Andric 285aed8d94eSDimitry Andrictemplate <class _Tp, bool = is_reference<_Tp>::value> 286aed8d94eSDimitry Andricstruct __optional_storage_base : __optional_destruct_base<_Tp> 287aed8d94eSDimitry Andric{ 288aed8d94eSDimitry Andric using __base = __optional_destruct_base<_Tp>; 289aed8d94eSDimitry Andric using value_type = _Tp; 290aed8d94eSDimitry Andric using __base::__base; 291aed8d94eSDimitry Andric 292aed8d94eSDimitry Andric _LIBCPP_INLINE_VISIBILITY 293aed8d94eSDimitry Andric constexpr bool has_value() const noexcept 294aed8d94eSDimitry Andric { 295aed8d94eSDimitry Andric return this->__engaged_; 296aed8d94eSDimitry Andric } 297aed8d94eSDimitry Andric 298aed8d94eSDimitry Andric _LIBCPP_INLINE_VISIBILITY 299aed8d94eSDimitry Andric constexpr value_type& __get() & noexcept 300aed8d94eSDimitry Andric { 301aed8d94eSDimitry Andric return this->__val_; 302aed8d94eSDimitry Andric } 303aed8d94eSDimitry Andric _LIBCPP_INLINE_VISIBILITY 304aed8d94eSDimitry Andric constexpr const value_type& __get() const& noexcept 305aed8d94eSDimitry Andric { 306aed8d94eSDimitry Andric return this->__val_; 307aed8d94eSDimitry Andric } 308aed8d94eSDimitry Andric _LIBCPP_INLINE_VISIBILITY 309aed8d94eSDimitry Andric constexpr value_type&& __get() && noexcept 310aed8d94eSDimitry Andric { 311aed8d94eSDimitry Andric return _VSTD::move(this->__val_); 312aed8d94eSDimitry Andric } 313aed8d94eSDimitry Andric _LIBCPP_INLINE_VISIBILITY 314aed8d94eSDimitry Andric constexpr const value_type&& __get() const&& noexcept 315aed8d94eSDimitry Andric { 316aed8d94eSDimitry Andric return _VSTD::move(this->__val_); 317aed8d94eSDimitry Andric } 318aed8d94eSDimitry Andric 319aed8d94eSDimitry Andric template <class... _Args> 320aed8d94eSDimitry Andric _LIBCPP_INLINE_VISIBILITY 321aed8d94eSDimitry Andric void __construct(_Args&&... __args) 322aed8d94eSDimitry Andric { 323aed8d94eSDimitry Andric _LIBCPP_ASSERT(!has_value(), "__construct called for engaged __optional_storage"); 324aed8d94eSDimitry Andric ::new((void*)_VSTD::addressof(this->__val_)) value_type(_VSTD::forward<_Args>(__args)...); 325aed8d94eSDimitry Andric this->__engaged_ = true; 326aed8d94eSDimitry Andric } 327aed8d94eSDimitry Andric 328aed8d94eSDimitry Andric template <class _That> 329aed8d94eSDimitry Andric _LIBCPP_INLINE_VISIBILITY 330aed8d94eSDimitry Andric void __construct_from(_That&& __opt) 331aed8d94eSDimitry Andric { 332aed8d94eSDimitry Andric if (__opt.has_value()) 333aed8d94eSDimitry Andric __construct(_VSTD::forward<_That>(__opt).__get()); 334aed8d94eSDimitry Andric } 335aed8d94eSDimitry Andric 336aed8d94eSDimitry Andric template <class _That> 337aed8d94eSDimitry Andric _LIBCPP_INLINE_VISIBILITY 338aed8d94eSDimitry Andric void __assign_from(_That&& __opt) 339aed8d94eSDimitry Andric { 340aed8d94eSDimitry Andric if (this->__engaged_ == __opt.has_value()) 341aed8d94eSDimitry Andric { 342aed8d94eSDimitry Andric if (this->__engaged_) 343aed8d94eSDimitry Andric this->__val_ = _VSTD::forward<_That>(__opt).__get(); 344aed8d94eSDimitry Andric } 345aed8d94eSDimitry Andric else 346aed8d94eSDimitry Andric { 347aed8d94eSDimitry Andric if (this->__engaged_) 348aed8d94eSDimitry Andric this->reset(); 349aed8d94eSDimitry Andric else 350aed8d94eSDimitry Andric __construct(_VSTD::forward<_That>(__opt).__get()); 351aed8d94eSDimitry Andric } 352aed8d94eSDimitry Andric } 353aed8d94eSDimitry Andric}; 354aed8d94eSDimitry Andric 355aed8d94eSDimitry Andric// optional<T&> is currently required ill-formed, however it may to be in the 356aed8d94eSDimitry Andric// future. For this reason it has already been implemented to ensure we can 357aed8d94eSDimitry Andric// make the change in an ABI compatible manner. 358aed8d94eSDimitry Andrictemplate <class _Tp> 359aed8d94eSDimitry Andricstruct __optional_storage_base<_Tp, true> 360aed8d94eSDimitry Andric{ 361aed8d94eSDimitry Andric using value_type = _Tp; 362aed8d94eSDimitry Andric using __raw_type = remove_reference_t<_Tp>; 363aed8d94eSDimitry Andric __raw_type* __value_; 364aed8d94eSDimitry Andric 365aed8d94eSDimitry Andric template <class _Up> 366aed8d94eSDimitry Andric static constexpr bool __can_bind_reference() { 367aed8d94eSDimitry Andric using _RawUp = typename remove_reference<_Up>::type; 368aed8d94eSDimitry Andric using _UpPtr = _RawUp*; 369aed8d94eSDimitry Andric using _RawTp = typename remove_reference<_Tp>::type; 370aed8d94eSDimitry Andric using _TpPtr = _RawTp*; 371aed8d94eSDimitry Andric using _CheckLValueArg = integral_constant<bool, 372aed8d94eSDimitry Andric (is_lvalue_reference<_Up>::value && is_convertible<_UpPtr, _TpPtr>::value) 373aed8d94eSDimitry Andric || is_same<_RawUp, reference_wrapper<_RawTp>>::value 374aed8d94eSDimitry Andric || is_same<_RawUp, reference_wrapper<typename remove_const<_RawTp>::type>>::value 375aed8d94eSDimitry Andric >; 376aed8d94eSDimitry Andric return (is_lvalue_reference<_Tp>::value && _CheckLValueArg::value) 377aed8d94eSDimitry Andric || (is_rvalue_reference<_Tp>::value && !is_lvalue_reference<_Up>::value && 378aed8d94eSDimitry Andric is_convertible<_UpPtr, _TpPtr>::value); 379aed8d94eSDimitry Andric } 380aed8d94eSDimitry Andric 381aed8d94eSDimitry Andric _LIBCPP_INLINE_VISIBILITY 382aed8d94eSDimitry Andric constexpr __optional_storage_base() noexcept 383aed8d94eSDimitry Andric : __value_(nullptr) {} 384aed8d94eSDimitry Andric 385aed8d94eSDimitry Andric template <class _UArg> 386aed8d94eSDimitry Andric _LIBCPP_INLINE_VISIBILITY 387aed8d94eSDimitry Andric constexpr explicit __optional_storage_base(in_place_t, _UArg&& __uarg) 388aed8d94eSDimitry Andric : __value_(_VSTD::addressof(__uarg)) 389aed8d94eSDimitry Andric { 390aed8d94eSDimitry Andric static_assert(__can_bind_reference<_UArg>(), 391aed8d94eSDimitry Andric "Attempted to construct a reference element in tuple from a " 392aed8d94eSDimitry Andric "possible temporary"); 393aed8d94eSDimitry Andric } 394aed8d94eSDimitry Andric 395aed8d94eSDimitry Andric _LIBCPP_INLINE_VISIBILITY 396aed8d94eSDimitry Andric void reset() noexcept { __value_ = nullptr; } 397aed8d94eSDimitry Andric 398aed8d94eSDimitry Andric _LIBCPP_INLINE_VISIBILITY 399aed8d94eSDimitry Andric constexpr bool has_value() const noexcept 400aed8d94eSDimitry Andric { return __value_ != nullptr; } 401aed8d94eSDimitry Andric 402aed8d94eSDimitry Andric _LIBCPP_INLINE_VISIBILITY 403aed8d94eSDimitry Andric constexpr value_type& __get() const& noexcept 404aed8d94eSDimitry Andric { return *__value_; } 405aed8d94eSDimitry Andric 406aed8d94eSDimitry Andric _LIBCPP_INLINE_VISIBILITY 407aed8d94eSDimitry Andric constexpr value_type&& __get() const&& noexcept 408aed8d94eSDimitry Andric { return _VSTD::forward<value_type>(*__value_); } 409aed8d94eSDimitry Andric 410aed8d94eSDimitry Andric template <class _UArg> 411aed8d94eSDimitry Andric _LIBCPP_INLINE_VISIBILITY 412aed8d94eSDimitry Andric void __construct(_UArg&& __val) 413aed8d94eSDimitry Andric { 414aed8d94eSDimitry Andric _LIBCPP_ASSERT(!has_value(), "__construct called for engaged __optional_storage"); 415aed8d94eSDimitry Andric static_assert(__can_bind_reference<_UArg>(), 416aed8d94eSDimitry Andric "Attempted to construct a reference element in tuple from a " 417aed8d94eSDimitry Andric "possible temporary"); 418aed8d94eSDimitry Andric __value_ = _VSTD::addressof(__val); 419aed8d94eSDimitry Andric } 420aed8d94eSDimitry Andric 421aed8d94eSDimitry Andric template <class _That> 422aed8d94eSDimitry Andric _LIBCPP_INLINE_VISIBILITY 423aed8d94eSDimitry Andric void __construct_from(_That&& __opt) 424aed8d94eSDimitry Andric { 425aed8d94eSDimitry Andric if (__opt.has_value()) 426aed8d94eSDimitry Andric __construct(_VSTD::forward<_That>(__opt).__get()); 427aed8d94eSDimitry Andric } 428aed8d94eSDimitry Andric 429aed8d94eSDimitry Andric template <class _That> 430aed8d94eSDimitry Andric _LIBCPP_INLINE_VISIBILITY 431aed8d94eSDimitry Andric void __assign_from(_That&& __opt) 432aed8d94eSDimitry Andric { 433aed8d94eSDimitry Andric if (has_value() == __opt.has_value()) 434aed8d94eSDimitry Andric { 435aed8d94eSDimitry Andric if (has_value()) 436aed8d94eSDimitry Andric *__value_ = _VSTD::forward<_That>(__opt).__get(); 437aed8d94eSDimitry Andric } 438aed8d94eSDimitry Andric else 439aed8d94eSDimitry Andric { 440aed8d94eSDimitry Andric if (has_value()) 441aed8d94eSDimitry Andric reset(); 442aed8d94eSDimitry Andric else 443aed8d94eSDimitry Andric __construct(_VSTD::forward<_That>(__opt).__get()); 444aed8d94eSDimitry Andric } 445aed8d94eSDimitry Andric } 446aed8d94eSDimitry Andric}; 447aed8d94eSDimitry Andric 448c4394386SDimitry Andrictemplate <class _Tp, bool = is_trivially_copy_constructible<_Tp>::value> 449c4394386SDimitry Andricstruct __optional_copy_base : __optional_storage_base<_Tp> 450aed8d94eSDimitry Andric{ 451aed8d94eSDimitry Andric using __optional_storage_base<_Tp>::__optional_storage_base; 452aed8d94eSDimitry Andric}; 453aed8d94eSDimitry Andric 454aed8d94eSDimitry Andrictemplate <class _Tp> 455c4394386SDimitry Andricstruct __optional_copy_base<_Tp, false> : __optional_storage_base<_Tp> 456aed8d94eSDimitry Andric{ 457aed8d94eSDimitry Andric using __optional_storage_base<_Tp>::__optional_storage_base; 458aed8d94eSDimitry Andric 459aed8d94eSDimitry Andric _LIBCPP_INLINE_VISIBILITY 460c4394386SDimitry Andric __optional_copy_base() = default; 461aed8d94eSDimitry Andric 462aed8d94eSDimitry Andric _LIBCPP_INLINE_VISIBILITY 463c4394386SDimitry Andric __optional_copy_base(const __optional_copy_base& __opt) 464aed8d94eSDimitry Andric { 465aed8d94eSDimitry Andric this->__construct_from(__opt); 466aed8d94eSDimitry Andric } 467aed8d94eSDimitry Andric 468aed8d94eSDimitry Andric _LIBCPP_INLINE_VISIBILITY 469c4394386SDimitry Andric __optional_copy_base(__optional_copy_base&&) = default; 470c4394386SDimitry Andric _LIBCPP_INLINE_VISIBILITY 471c4394386SDimitry Andric __optional_copy_base& operator=(const __optional_copy_base&) = default; 472c4394386SDimitry Andric _LIBCPP_INLINE_VISIBILITY 473c4394386SDimitry Andric __optional_copy_base& operator=(__optional_copy_base&&) = default; 474c4394386SDimitry Andric}; 475c4394386SDimitry Andric 476c4394386SDimitry Andrictemplate <class _Tp, bool = is_trivially_move_constructible<_Tp>::value> 477c4394386SDimitry Andricstruct __optional_move_base : __optional_copy_base<_Tp> 478c4394386SDimitry Andric{ 479c4394386SDimitry Andric using __optional_copy_base<_Tp>::__optional_copy_base; 480c4394386SDimitry Andric}; 481c4394386SDimitry Andric 482c4394386SDimitry Andrictemplate <class _Tp> 483c4394386SDimitry Andricstruct __optional_move_base<_Tp, false> : __optional_copy_base<_Tp> 484c4394386SDimitry Andric{ 485c4394386SDimitry Andric using value_type = _Tp; 486c4394386SDimitry Andric using __optional_copy_base<_Tp>::__optional_copy_base; 487c4394386SDimitry Andric 488c4394386SDimitry Andric _LIBCPP_INLINE_VISIBILITY 489c4394386SDimitry Andric __optional_move_base() = default; 490c4394386SDimitry Andric _LIBCPP_INLINE_VISIBILITY 491c4394386SDimitry Andric __optional_move_base(const __optional_move_base&) = default; 492c4394386SDimitry Andric 493c4394386SDimitry Andric _LIBCPP_INLINE_VISIBILITY 494c4394386SDimitry Andric __optional_move_base(__optional_move_base&& __opt) 495aed8d94eSDimitry Andric noexcept(is_nothrow_move_constructible_v<value_type>) 496aed8d94eSDimitry Andric { 497aed8d94eSDimitry Andric this->__construct_from(_VSTD::move(__opt)); 498aed8d94eSDimitry Andric } 499aed8d94eSDimitry Andric 500aed8d94eSDimitry Andric _LIBCPP_INLINE_VISIBILITY 501c4394386SDimitry Andric __optional_move_base& operator=(const __optional_move_base&) = default; 502c4394386SDimitry Andric _LIBCPP_INLINE_VISIBILITY 503c4394386SDimitry Andric __optional_move_base& operator=(__optional_move_base&&) = default; 504c4394386SDimitry Andric}; 505c4394386SDimitry Andric 506c4394386SDimitry Andrictemplate <class _Tp, bool = 507c4394386SDimitry Andric is_trivially_destructible<_Tp>::value && 508c4394386SDimitry Andric is_trivially_copy_constructible<_Tp>::value && 509c4394386SDimitry Andric is_trivially_copy_assignable<_Tp>::value> 510c4394386SDimitry Andricstruct __optional_copy_assign_base : __optional_move_base<_Tp> 511c4394386SDimitry Andric{ 512c4394386SDimitry Andric using __optional_move_base<_Tp>::__optional_move_base; 513c4394386SDimitry Andric}; 514c4394386SDimitry Andric 515c4394386SDimitry Andrictemplate <class _Tp> 516c4394386SDimitry Andricstruct __optional_copy_assign_base<_Tp, false> : __optional_move_base<_Tp> 517c4394386SDimitry Andric{ 518c4394386SDimitry Andric using __optional_move_base<_Tp>::__optional_move_base; 519c4394386SDimitry Andric 520c4394386SDimitry Andric _LIBCPP_INLINE_VISIBILITY 521c4394386SDimitry Andric __optional_copy_assign_base() = default; 522c4394386SDimitry Andric _LIBCPP_INLINE_VISIBILITY 523c4394386SDimitry Andric __optional_copy_assign_base(const __optional_copy_assign_base&) = default; 524c4394386SDimitry Andric _LIBCPP_INLINE_VISIBILITY 525c4394386SDimitry Andric __optional_copy_assign_base(__optional_copy_assign_base&&) = default; 526c4394386SDimitry Andric 527c4394386SDimitry Andric _LIBCPP_INLINE_VISIBILITY 528c4394386SDimitry Andric __optional_copy_assign_base& operator=(const __optional_copy_assign_base& __opt) 529aed8d94eSDimitry Andric { 530aed8d94eSDimitry Andric this->__assign_from(__opt); 531aed8d94eSDimitry Andric return *this; 532aed8d94eSDimitry Andric } 533aed8d94eSDimitry Andric 534aed8d94eSDimitry Andric _LIBCPP_INLINE_VISIBILITY 535c4394386SDimitry Andric __optional_copy_assign_base& operator=(__optional_copy_assign_base&&) = default; 536c4394386SDimitry Andric}; 537c4394386SDimitry Andric 538c4394386SDimitry Andrictemplate <class _Tp, bool = 539c4394386SDimitry Andric is_trivially_destructible<_Tp>::value && 540c4394386SDimitry Andric is_trivially_move_constructible<_Tp>::value && 541c4394386SDimitry Andric is_trivially_move_assignable<_Tp>::value> 542c4394386SDimitry Andricstruct __optional_move_assign_base : __optional_copy_assign_base<_Tp> 543c4394386SDimitry Andric{ 544c4394386SDimitry Andric using __optional_copy_assign_base<_Tp>::__optional_copy_assign_base; 545c4394386SDimitry Andric}; 546c4394386SDimitry Andric 547c4394386SDimitry Andrictemplate <class _Tp> 548c4394386SDimitry Andricstruct __optional_move_assign_base<_Tp, false> : __optional_copy_assign_base<_Tp> 549c4394386SDimitry Andric{ 550c4394386SDimitry Andric using value_type = _Tp; 551c4394386SDimitry Andric using __optional_copy_assign_base<_Tp>::__optional_copy_assign_base; 552c4394386SDimitry Andric 553c4394386SDimitry Andric _LIBCPP_INLINE_VISIBILITY 554c4394386SDimitry Andric __optional_move_assign_base() = default; 555c4394386SDimitry Andric _LIBCPP_INLINE_VISIBILITY 556c4394386SDimitry Andric __optional_move_assign_base(const __optional_move_assign_base& __opt) = default; 557c4394386SDimitry Andric _LIBCPP_INLINE_VISIBILITY 558c4394386SDimitry Andric __optional_move_assign_base(__optional_move_assign_base&&) = default; 559c4394386SDimitry Andric _LIBCPP_INLINE_VISIBILITY 560c4394386SDimitry Andric __optional_move_assign_base& operator=(const __optional_move_assign_base&) = default; 561c4394386SDimitry Andric 562c4394386SDimitry Andric _LIBCPP_INLINE_VISIBILITY 563c4394386SDimitry Andric __optional_move_assign_base& operator=(__optional_move_assign_base&& __opt) 564aed8d94eSDimitry Andric noexcept(is_nothrow_move_assignable_v<value_type> && 565aed8d94eSDimitry Andric is_nothrow_move_constructible_v<value_type>) 566aed8d94eSDimitry Andric { 567aed8d94eSDimitry Andric this->__assign_from(_VSTD::move(__opt)); 568aed8d94eSDimitry Andric return *this; 569aed8d94eSDimitry Andric } 570aed8d94eSDimitry Andric}; 571aed8d94eSDimitry Andric 572aed8d94eSDimitry Andrictemplate <class _Tp> 573aed8d94eSDimitry Andricusing __optional_sfinae_ctor_base_t = __sfinae_ctor_base< 574aed8d94eSDimitry Andric is_copy_constructible<_Tp>::value, 575aed8d94eSDimitry Andric is_move_constructible<_Tp>::value 576aed8d94eSDimitry Andric>; 577aed8d94eSDimitry Andric 578aed8d94eSDimitry Andrictemplate <class _Tp> 579aed8d94eSDimitry Andricusing __optional_sfinae_assign_base_t = __sfinae_assign_base< 580aed8d94eSDimitry Andric (is_copy_constructible<_Tp>::value && is_copy_assignable<_Tp>::value), 581aed8d94eSDimitry Andric (is_move_constructible<_Tp>::value && is_move_assignable<_Tp>::value) 582aed8d94eSDimitry Andric>; 583aed8d94eSDimitry Andric 584aed8d94eSDimitry Andrictemplate <class _Tp> 585aed8d94eSDimitry Andricclass optional 586c4394386SDimitry Andric : private __optional_move_assign_base<_Tp> 587aed8d94eSDimitry Andric , private __optional_sfinae_ctor_base_t<_Tp> 588aed8d94eSDimitry Andric , private __optional_sfinae_assign_base_t<_Tp> 589aed8d94eSDimitry Andric{ 590c4394386SDimitry Andric using __base = __optional_move_assign_base<_Tp>; 591aed8d94eSDimitry Andricpublic: 592aed8d94eSDimitry Andric using value_type = _Tp; 593aed8d94eSDimitry Andric 594aed8d94eSDimitry Andricprivate: 595aed8d94eSDimitry Andric // Disable the reference extension using this static assert. 596aed8d94eSDimitry Andric static_assert(!is_same_v<value_type, in_place_t>, 597aed8d94eSDimitry Andric "instantiation of optional with in_place_t is ill-formed"); 598aed8d94eSDimitry Andric static_assert(!is_same_v<__uncvref_t<value_type>, nullopt_t>, 599aed8d94eSDimitry Andric "instantiation of optional with nullopt_t is ill-formed"); 600aed8d94eSDimitry Andric static_assert(!is_reference_v<value_type>, 601aed8d94eSDimitry Andric "instantiation of optional with a reference type is ill-formed"); 602aed8d94eSDimitry Andric static_assert(is_destructible_v<value_type>, 603aed8d94eSDimitry Andric "instantiation of optional with a non-destructible type is ill-formed"); 604aed8d94eSDimitry Andric 605aed8d94eSDimitry Andric // LWG2756: conditionally explicit conversion from _Up 606aed8d94eSDimitry Andric struct _CheckOptionalArgsConstructor { 607aed8d94eSDimitry Andric template <class _Up> 608aed8d94eSDimitry Andric static constexpr bool __enable_implicit() { 609aed8d94eSDimitry Andric return is_constructible_v<_Tp, _Up&&> && 610aed8d94eSDimitry Andric is_convertible_v<_Up&&, _Tp>; 611aed8d94eSDimitry Andric } 612aed8d94eSDimitry Andric 613aed8d94eSDimitry Andric template <class _Up> 614aed8d94eSDimitry Andric static constexpr bool __enable_explicit() { 615aed8d94eSDimitry Andric return is_constructible_v<_Tp, _Up&&> && 616aed8d94eSDimitry Andric !is_convertible_v<_Up&&, _Tp>; 617aed8d94eSDimitry Andric } 618aed8d94eSDimitry Andric }; 619aed8d94eSDimitry Andric template <class _Up> 620aed8d94eSDimitry Andric using _CheckOptionalArgsCtor = conditional_t< 6214ba319b5SDimitry Andric !is_same_v<__uncvref_t<_Up>, in_place_t> && 6224ba319b5SDimitry Andric !is_same_v<__uncvref_t<_Up>, optional>, 623aed8d94eSDimitry Andric _CheckOptionalArgsConstructor, 624aed8d94eSDimitry Andric __check_tuple_constructor_fail 625aed8d94eSDimitry Andric >; 626aed8d94eSDimitry Andric template <class _QualUp> 627aed8d94eSDimitry Andric struct _CheckOptionalLikeConstructor { 628aed8d94eSDimitry Andric template <class _Up, class _Opt = optional<_Up>> 629aed8d94eSDimitry Andric using __check_constructible_from_opt = __lazy_or< 630aed8d94eSDimitry Andric is_constructible<_Tp, _Opt&>, 631aed8d94eSDimitry Andric is_constructible<_Tp, _Opt const&>, 632aed8d94eSDimitry Andric is_constructible<_Tp, _Opt&&>, 633aed8d94eSDimitry Andric is_constructible<_Tp, _Opt const&&>, 634aed8d94eSDimitry Andric is_convertible<_Opt&, _Tp>, 635aed8d94eSDimitry Andric is_convertible<_Opt const&, _Tp>, 636aed8d94eSDimitry Andric is_convertible<_Opt&&, _Tp>, 637aed8d94eSDimitry Andric is_convertible<_Opt const&&, _Tp> 638aed8d94eSDimitry Andric >; 639aed8d94eSDimitry Andric template <class _Up, class _Opt = optional<_Up>> 640aed8d94eSDimitry Andric using __check_assignable_from_opt = __lazy_or< 641aed8d94eSDimitry Andric is_assignable<_Tp&, _Opt&>, 642aed8d94eSDimitry Andric is_assignable<_Tp&, _Opt const&>, 643aed8d94eSDimitry Andric is_assignable<_Tp&, _Opt&&>, 644aed8d94eSDimitry Andric is_assignable<_Tp&, _Opt const&&> 645aed8d94eSDimitry Andric >; 646aed8d94eSDimitry Andric template <class _Up, class _QUp = _QualUp> 647aed8d94eSDimitry Andric static constexpr bool __enable_implicit() { 648aed8d94eSDimitry Andric return is_convertible<_QUp, _Tp>::value && 649aed8d94eSDimitry Andric !__check_constructible_from_opt<_Up>::value; 650aed8d94eSDimitry Andric } 651aed8d94eSDimitry Andric template <class _Up, class _QUp = _QualUp> 652aed8d94eSDimitry Andric static constexpr bool __enable_explicit() { 653aed8d94eSDimitry Andric return !is_convertible<_QUp, _Tp>::value && 654aed8d94eSDimitry Andric !__check_constructible_from_opt<_Up>::value; 655aed8d94eSDimitry Andric } 656aed8d94eSDimitry Andric template <class _Up, class _QUp = _QualUp> 657aed8d94eSDimitry Andric static constexpr bool __enable_assign() { 658aed8d94eSDimitry Andric // Construction and assignability of _Qup to _Tp has already been 659aed8d94eSDimitry Andric // checked. 660aed8d94eSDimitry Andric return !__check_constructible_from_opt<_Up>::value && 661aed8d94eSDimitry Andric !__check_assignable_from_opt<_Up>::value; 662aed8d94eSDimitry Andric } 663aed8d94eSDimitry Andric }; 664aed8d94eSDimitry Andric 665aed8d94eSDimitry Andric template <class _Up, class _QualUp> 666aed8d94eSDimitry Andric using _CheckOptionalLikeCtor = conditional_t< 667aed8d94eSDimitry Andric __lazy_and< 668aed8d94eSDimitry Andric __lazy_not<is_same<_Up, _Tp>>, 669aed8d94eSDimitry Andric is_constructible<_Tp, _QualUp> 670aed8d94eSDimitry Andric >::value, 671aed8d94eSDimitry Andric _CheckOptionalLikeConstructor<_QualUp>, 672aed8d94eSDimitry Andric __check_tuple_constructor_fail 673aed8d94eSDimitry Andric >; 674aed8d94eSDimitry Andric template <class _Up, class _QualUp> 675aed8d94eSDimitry Andric using _CheckOptionalLikeAssign = conditional_t< 676aed8d94eSDimitry Andric __lazy_and< 677aed8d94eSDimitry Andric __lazy_not<is_same<_Up, _Tp>>, 678aed8d94eSDimitry Andric is_constructible<_Tp, _QualUp>, 679aed8d94eSDimitry Andric is_assignable<_Tp&, _QualUp> 680aed8d94eSDimitry Andric >::value, 681aed8d94eSDimitry Andric _CheckOptionalLikeConstructor<_QualUp>, 682aed8d94eSDimitry Andric __check_tuple_constructor_fail 683aed8d94eSDimitry Andric >; 684aed8d94eSDimitry Andricpublic: 685aed8d94eSDimitry Andric 686aed8d94eSDimitry Andric _LIBCPP_INLINE_VISIBILITY constexpr optional() noexcept {} 68760ff8e32SDimitry Andric _LIBCPP_INLINE_VISIBILITY constexpr optional(const optional&) = default; 68860ff8e32SDimitry Andric _LIBCPP_INLINE_VISIBILITY constexpr optional(optional&&) = default; 689aed8d94eSDimitry Andric _LIBCPP_INLINE_VISIBILITY constexpr optional(nullopt_t) noexcept {} 690aed8d94eSDimitry Andric 691aed8d94eSDimitry Andric template <class... _Args, class = enable_if_t< 692aed8d94eSDimitry Andric is_constructible_v<value_type, _Args...>> 693aed8d94eSDimitry Andric > 694aed8d94eSDimitry Andric _LIBCPP_INLINE_VISIBILITY 695aed8d94eSDimitry Andric constexpr explicit optional(in_place_t, _Args&&... __args) 696aed8d94eSDimitry Andric : __base(in_place, _VSTD::forward<_Args>(__args)...) {} 697aed8d94eSDimitry Andric 698aed8d94eSDimitry Andric template <class _Up, class... _Args, class = enable_if_t< 699aed8d94eSDimitry Andric is_constructible_v<value_type, initializer_list<_Up>&, _Args...>> 700aed8d94eSDimitry Andric > 701aed8d94eSDimitry Andric _LIBCPP_INLINE_VISIBILITY 702aed8d94eSDimitry Andric constexpr explicit optional(in_place_t, initializer_list<_Up> __il, _Args&&... __args) 703aed8d94eSDimitry Andric : __base(in_place, __il, _VSTD::forward<_Args>(__args)...) {} 704aed8d94eSDimitry Andric 705aed8d94eSDimitry Andric template <class _Up = value_type, enable_if_t< 706aed8d94eSDimitry Andric _CheckOptionalArgsCtor<_Up>::template __enable_implicit<_Up>() 707aed8d94eSDimitry Andric , int> = 0> 708aed8d94eSDimitry Andric _LIBCPP_INLINE_VISIBILITY 709aed8d94eSDimitry Andric constexpr optional(_Up&& __v) 710aed8d94eSDimitry Andric : __base(in_place, _VSTD::forward<_Up>(__v)) {} 711aed8d94eSDimitry Andric 712aed8d94eSDimitry Andric template <class _Up, enable_if_t< 713aed8d94eSDimitry Andric _CheckOptionalArgsCtor<_Up>::template __enable_explicit<_Up>() 714aed8d94eSDimitry Andric , int> = 0> 715aed8d94eSDimitry Andric _LIBCPP_INLINE_VISIBILITY 716aed8d94eSDimitry Andric constexpr explicit optional(_Up&& __v) 717aed8d94eSDimitry Andric : __base(in_place, _VSTD::forward<_Up>(__v)) {} 718aed8d94eSDimitry Andric 719aed8d94eSDimitry Andric // LWG2756: conditionally explicit conversion from const optional<_Up>& 720aed8d94eSDimitry Andric template <class _Up, enable_if_t< 721aed8d94eSDimitry Andric _CheckOptionalLikeCtor<_Up, _Up const&>::template __enable_implicit<_Up>() 722aed8d94eSDimitry Andric , int> = 0> 723aed8d94eSDimitry Andric _LIBCPP_INLINE_VISIBILITY 724aed8d94eSDimitry Andric optional(const optional<_Up>& __v) 725aed8d94eSDimitry Andric { 726aed8d94eSDimitry Andric this->__construct_from(__v); 727aed8d94eSDimitry Andric } 728aed8d94eSDimitry Andric template <class _Up, enable_if_t< 729aed8d94eSDimitry Andric _CheckOptionalLikeCtor<_Up, _Up const&>::template __enable_explicit<_Up>() 730aed8d94eSDimitry Andric , int> = 0> 731aed8d94eSDimitry Andric _LIBCPP_INLINE_VISIBILITY 732aed8d94eSDimitry Andric explicit optional(const optional<_Up>& __v) 733aed8d94eSDimitry Andric { 734aed8d94eSDimitry Andric this->__construct_from(__v); 735aed8d94eSDimitry Andric } 736aed8d94eSDimitry Andric 737aed8d94eSDimitry Andric // LWG2756: conditionally explicit conversion from optional<_Up>&& 738aed8d94eSDimitry Andric template <class _Up, enable_if_t< 739aed8d94eSDimitry Andric _CheckOptionalLikeCtor<_Up, _Up &&>::template __enable_implicit<_Up>() 740aed8d94eSDimitry Andric , int> = 0> 741aed8d94eSDimitry Andric _LIBCPP_INLINE_VISIBILITY 742aed8d94eSDimitry Andric optional(optional<_Up>&& __v) 743aed8d94eSDimitry Andric { 744aed8d94eSDimitry Andric this->__construct_from(_VSTD::move(__v)); 745aed8d94eSDimitry Andric } 746aed8d94eSDimitry Andric template <class _Up, enable_if_t< 747aed8d94eSDimitry Andric _CheckOptionalLikeCtor<_Up, _Up &&>::template __enable_explicit<_Up>() 748aed8d94eSDimitry Andric , int> = 0> 749aed8d94eSDimitry Andric _LIBCPP_INLINE_VISIBILITY 750aed8d94eSDimitry Andric explicit optional(optional<_Up>&& __v) 751aed8d94eSDimitry Andric { 752aed8d94eSDimitry Andric this->__construct_from(_VSTD::move(__v)); 753aed8d94eSDimitry Andric } 754aed8d94eSDimitry Andric 755aed8d94eSDimitry Andric _LIBCPP_INLINE_VISIBILITY 756aed8d94eSDimitry Andric optional& operator=(nullopt_t) noexcept 757aed8d94eSDimitry Andric { 758aed8d94eSDimitry Andric reset(); 759aed8d94eSDimitry Andric return *this; 760aed8d94eSDimitry Andric } 761aed8d94eSDimitry Andric 762aed8d94eSDimitry Andric _LIBCPP_INLINE_VISIBILITY optional& operator=(const optional&) = default; 763aed8d94eSDimitry Andric _LIBCPP_INLINE_VISIBILITY optional& operator=(optional&&) = default; 764aed8d94eSDimitry Andric 765aed8d94eSDimitry Andric // LWG2756 766aed8d94eSDimitry Andric template <class _Up = value_type, 767aed8d94eSDimitry Andric class = enable_if_t 768aed8d94eSDimitry Andric <__lazy_and< 769aed8d94eSDimitry Andric integral_constant<bool, 7704ba319b5SDimitry Andric !is_same_v<__uncvref_t<_Up>, optional> && 771aed8d94eSDimitry Andric !(is_same_v<_Up, value_type> && is_scalar_v<value_type>) 772aed8d94eSDimitry Andric >, 773aed8d94eSDimitry Andric is_constructible<value_type, _Up>, 774aed8d94eSDimitry Andric is_assignable<value_type&, _Up> 775aed8d94eSDimitry Andric >::value> 776aed8d94eSDimitry Andric > 777aed8d94eSDimitry Andric _LIBCPP_INLINE_VISIBILITY 778aed8d94eSDimitry Andric optional& 779aed8d94eSDimitry Andric operator=(_Up&& __v) 780aed8d94eSDimitry Andric { 781aed8d94eSDimitry Andric if (this->has_value()) 782aed8d94eSDimitry Andric this->__get() = _VSTD::forward<_Up>(__v); 783aed8d94eSDimitry Andric else 784aed8d94eSDimitry Andric this->__construct(_VSTD::forward<_Up>(__v)); 785aed8d94eSDimitry Andric return *this; 786aed8d94eSDimitry Andric } 787aed8d94eSDimitry Andric 788aed8d94eSDimitry Andric // LWG2756 789aed8d94eSDimitry Andric template <class _Up, enable_if_t< 790aed8d94eSDimitry Andric _CheckOptionalLikeAssign<_Up, _Up const&>::template __enable_assign<_Up>() 791aed8d94eSDimitry Andric , int> = 0> 792aed8d94eSDimitry Andric _LIBCPP_INLINE_VISIBILITY 793aed8d94eSDimitry Andric optional& 794aed8d94eSDimitry Andric operator=(const optional<_Up>& __v) 795aed8d94eSDimitry Andric { 796aed8d94eSDimitry Andric this->__assign_from(__v); 797aed8d94eSDimitry Andric return *this; 798aed8d94eSDimitry Andric } 799aed8d94eSDimitry Andric 800aed8d94eSDimitry Andric // LWG2756 801aed8d94eSDimitry Andric template <class _Up, enable_if_t< 802aed8d94eSDimitry Andric _CheckOptionalLikeCtor<_Up, _Up &&>::template __enable_assign<_Up>() 803aed8d94eSDimitry Andric , int> = 0> 804aed8d94eSDimitry Andric _LIBCPP_INLINE_VISIBILITY 805aed8d94eSDimitry Andric optional& 806aed8d94eSDimitry Andric operator=(optional<_Up>&& __v) 807aed8d94eSDimitry Andric { 808aed8d94eSDimitry Andric this->__assign_from(_VSTD::move(__v)); 809aed8d94eSDimitry Andric return *this; 810aed8d94eSDimitry Andric } 811aed8d94eSDimitry Andric 812aed8d94eSDimitry Andric template <class... _Args, 813aed8d94eSDimitry Andric class = enable_if_t 814aed8d94eSDimitry Andric < 815aed8d94eSDimitry Andric is_constructible_v<value_type, _Args...> 816aed8d94eSDimitry Andric > 817aed8d94eSDimitry Andric > 818aed8d94eSDimitry Andric _LIBCPP_INLINE_VISIBILITY 819540d2a8bSDimitry Andric _Tp & 820aed8d94eSDimitry Andric emplace(_Args&&... __args) 821aed8d94eSDimitry Andric { 822aed8d94eSDimitry Andric reset(); 823aed8d94eSDimitry Andric this->__construct(_VSTD::forward<_Args>(__args)...); 824540d2a8bSDimitry Andric return this->__get(); 825aed8d94eSDimitry Andric } 826aed8d94eSDimitry Andric 827aed8d94eSDimitry Andric template <class _Up, class... _Args, 828aed8d94eSDimitry Andric class = enable_if_t 829aed8d94eSDimitry Andric < 830aed8d94eSDimitry Andric is_constructible_v<value_type, initializer_list<_Up>&, _Args...> 831aed8d94eSDimitry Andric > 832aed8d94eSDimitry Andric > 833aed8d94eSDimitry Andric _LIBCPP_INLINE_VISIBILITY 834540d2a8bSDimitry Andric _Tp & 835aed8d94eSDimitry Andric emplace(initializer_list<_Up> __il, _Args&&... __args) 836aed8d94eSDimitry Andric { 837aed8d94eSDimitry Andric reset(); 838aed8d94eSDimitry Andric this->__construct(__il, _VSTD::forward<_Args>(__args)...); 839540d2a8bSDimitry Andric return this->__get(); 840aed8d94eSDimitry Andric } 841aed8d94eSDimitry Andric 842aed8d94eSDimitry Andric _LIBCPP_INLINE_VISIBILITY 843aed8d94eSDimitry Andric void swap(optional& __opt) 844aed8d94eSDimitry Andric noexcept(is_nothrow_move_constructible_v<value_type> && 845aed8d94eSDimitry Andric is_nothrow_swappable_v<value_type>) 846aed8d94eSDimitry Andric { 847aed8d94eSDimitry Andric if (this->has_value() == __opt.has_value()) 848aed8d94eSDimitry Andric { 849aed8d94eSDimitry Andric using _VSTD::swap; 850aed8d94eSDimitry Andric if (this->has_value()) 851aed8d94eSDimitry Andric swap(this->__get(), __opt.__get()); 852aed8d94eSDimitry Andric } 853aed8d94eSDimitry Andric else 854aed8d94eSDimitry Andric { 855aed8d94eSDimitry Andric if (this->has_value()) 856aed8d94eSDimitry Andric { 857aed8d94eSDimitry Andric __opt.__construct(_VSTD::move(this->__get())); 858aed8d94eSDimitry Andric reset(); 859aed8d94eSDimitry Andric } 860aed8d94eSDimitry Andric else 861aed8d94eSDimitry Andric { 862aed8d94eSDimitry Andric this->__construct(_VSTD::move(__opt.__get())); 863aed8d94eSDimitry Andric __opt.reset(); 864aed8d94eSDimitry Andric } 865aed8d94eSDimitry Andric } 866aed8d94eSDimitry Andric } 867aed8d94eSDimitry Andric 868aed8d94eSDimitry Andric _LIBCPP_INLINE_VISIBILITY 869aed8d94eSDimitry Andric constexpr 870aed8d94eSDimitry Andric add_pointer_t<value_type const> 871aed8d94eSDimitry Andric operator->() const 872aed8d94eSDimitry Andric { 873aed8d94eSDimitry Andric _LIBCPP_ASSERT(this->has_value(), "optional operator-> called for disengaged value"); 874aed8d94eSDimitry Andric#ifndef _LIBCPP_HAS_NO_BUILTIN_ADDRESSOF 875aed8d94eSDimitry Andric return _VSTD::addressof(this->__get()); 876aed8d94eSDimitry Andric#else 877aed8d94eSDimitry Andric return __operator_arrow(__has_operator_addressof<value_type>{}, this->__get()); 878aed8d94eSDimitry Andric#endif 879aed8d94eSDimitry Andric } 880aed8d94eSDimitry Andric 881aed8d94eSDimitry Andric _LIBCPP_INLINE_VISIBILITY 882aed8d94eSDimitry Andric constexpr 883aed8d94eSDimitry Andric add_pointer_t<value_type> 884aed8d94eSDimitry Andric operator->() 885aed8d94eSDimitry Andric { 886aed8d94eSDimitry Andric _LIBCPP_ASSERT(this->has_value(), "optional operator-> called for disengaged value"); 887aed8d94eSDimitry Andric#ifndef _LIBCPP_HAS_NO_BUILTIN_ADDRESSOF 888aed8d94eSDimitry Andric return _VSTD::addressof(this->__get()); 889aed8d94eSDimitry Andric#else 890aed8d94eSDimitry Andric return __operator_arrow(__has_operator_addressof<value_type>{}, this->__get()); 891aed8d94eSDimitry Andric#endif 892aed8d94eSDimitry Andric } 893aed8d94eSDimitry Andric 894aed8d94eSDimitry Andric _LIBCPP_INLINE_VISIBILITY 895aed8d94eSDimitry Andric constexpr 896aed8d94eSDimitry Andric const value_type& 897aed8d94eSDimitry Andric operator*() const& 898aed8d94eSDimitry Andric { 899aed8d94eSDimitry Andric _LIBCPP_ASSERT(this->has_value(), "optional operator* called for disengaged value"); 900aed8d94eSDimitry Andric return this->__get(); 901aed8d94eSDimitry Andric } 902aed8d94eSDimitry Andric 903aed8d94eSDimitry Andric _LIBCPP_INLINE_VISIBILITY 904aed8d94eSDimitry Andric constexpr 905aed8d94eSDimitry Andric value_type& 906aed8d94eSDimitry Andric operator*() & 907aed8d94eSDimitry Andric { 908aed8d94eSDimitry Andric _LIBCPP_ASSERT(this->has_value(), "optional operator* called for disengaged value"); 909aed8d94eSDimitry Andric return this->__get(); 910aed8d94eSDimitry Andric } 911aed8d94eSDimitry Andric 912aed8d94eSDimitry Andric _LIBCPP_INLINE_VISIBILITY 913aed8d94eSDimitry Andric constexpr 914aed8d94eSDimitry Andric value_type&& 915aed8d94eSDimitry Andric operator*() && 916aed8d94eSDimitry Andric { 917aed8d94eSDimitry Andric _LIBCPP_ASSERT(this->has_value(), "optional operator* called for disengaged value"); 918aed8d94eSDimitry Andric return _VSTD::move(this->__get()); 919aed8d94eSDimitry Andric } 920aed8d94eSDimitry Andric 921aed8d94eSDimitry Andric _LIBCPP_INLINE_VISIBILITY 922aed8d94eSDimitry Andric constexpr 923aed8d94eSDimitry Andric const value_type&& 924aed8d94eSDimitry Andric operator*() const&& 925aed8d94eSDimitry Andric { 926aed8d94eSDimitry Andric _LIBCPP_ASSERT(this->has_value(), "optional operator* called for disengaged value"); 927aed8d94eSDimitry Andric return _VSTD::move(this->__get()); 928aed8d94eSDimitry Andric } 929aed8d94eSDimitry Andric 930aed8d94eSDimitry Andric _LIBCPP_INLINE_VISIBILITY 931aed8d94eSDimitry Andric constexpr explicit operator bool() const noexcept { return has_value(); } 932aed8d94eSDimitry Andric 933aed8d94eSDimitry Andric using __base::has_value; 934aed8d94eSDimitry Andric using __base::__get; 935aed8d94eSDimitry Andric 936aed8d94eSDimitry Andric _LIBCPP_INLINE_VISIBILITY 937*b5893f02SDimitry Andric _LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS 938aed8d94eSDimitry Andric constexpr value_type const& value() const& 939aed8d94eSDimitry Andric { 940aed8d94eSDimitry Andric if (!this->has_value()) 941aed8d94eSDimitry Andric __throw_bad_optional_access(); 942aed8d94eSDimitry Andric return this->__get(); 943aed8d94eSDimitry Andric } 944aed8d94eSDimitry Andric 945aed8d94eSDimitry Andric _LIBCPP_INLINE_VISIBILITY 946*b5893f02SDimitry Andric _LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS 947aed8d94eSDimitry Andric constexpr value_type& value() & 948aed8d94eSDimitry Andric { 949aed8d94eSDimitry Andric if (!this->has_value()) 950aed8d94eSDimitry Andric __throw_bad_optional_access(); 951aed8d94eSDimitry Andric return this->__get(); 952aed8d94eSDimitry Andric } 953aed8d94eSDimitry Andric 954aed8d94eSDimitry Andric _LIBCPP_INLINE_VISIBILITY 955*b5893f02SDimitry Andric _LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS 956aed8d94eSDimitry Andric constexpr value_type&& value() && 957aed8d94eSDimitry Andric { 958aed8d94eSDimitry Andric if (!this->has_value()) 959aed8d94eSDimitry Andric __throw_bad_optional_access(); 960aed8d94eSDimitry Andric return _VSTD::move(this->__get()); 961aed8d94eSDimitry Andric } 962aed8d94eSDimitry Andric 963aed8d94eSDimitry Andric _LIBCPP_INLINE_VISIBILITY 964*b5893f02SDimitry Andric _LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS 965aed8d94eSDimitry Andric constexpr value_type const&& value() const&& 966aed8d94eSDimitry Andric { 967aed8d94eSDimitry Andric if (!this->has_value()) 968aed8d94eSDimitry Andric __throw_bad_optional_access(); 969aed8d94eSDimitry Andric return _VSTD::move(this->__get()); 970aed8d94eSDimitry Andric } 971aed8d94eSDimitry Andric 972aed8d94eSDimitry Andric template <class _Up> 973aed8d94eSDimitry Andric _LIBCPP_INLINE_VISIBILITY 974aed8d94eSDimitry Andric constexpr value_type value_or(_Up&& __v) const& 975aed8d94eSDimitry Andric { 976aed8d94eSDimitry Andric static_assert(is_copy_constructible_v<value_type>, 977aed8d94eSDimitry Andric "optional<T>::value_or: T must be copy constructible"); 978aed8d94eSDimitry Andric static_assert(is_convertible_v<_Up, value_type>, 979aed8d94eSDimitry Andric "optional<T>::value_or: U must be convertible to T"); 980aed8d94eSDimitry Andric return this->has_value() ? this->__get() : 981aed8d94eSDimitry Andric static_cast<value_type>(_VSTD::forward<_Up>(__v)); 982aed8d94eSDimitry Andric } 983aed8d94eSDimitry Andric 984aed8d94eSDimitry Andric template <class _Up> 985aed8d94eSDimitry Andric _LIBCPP_INLINE_VISIBILITY 986db17bf38SDimitry Andric constexpr value_type value_or(_Up&& __v) && 987aed8d94eSDimitry Andric { 988aed8d94eSDimitry Andric static_assert(is_move_constructible_v<value_type>, 989aed8d94eSDimitry Andric "optional<T>::value_or: T must be move constructible"); 990aed8d94eSDimitry Andric static_assert(is_convertible_v<_Up, value_type>, 991aed8d94eSDimitry Andric "optional<T>::value_or: U must be convertible to T"); 992aed8d94eSDimitry Andric return this->has_value() ? _VSTD::move(this->__get()) : 993aed8d94eSDimitry Andric static_cast<value_type>(_VSTD::forward<_Up>(__v)); 994aed8d94eSDimitry Andric } 995aed8d94eSDimitry Andric 996aed8d94eSDimitry Andric using __base::reset; 997aed8d94eSDimitry Andric 998aed8d94eSDimitry Andricprivate: 999aed8d94eSDimitry Andric template <class _Up> 1000aed8d94eSDimitry Andric _LIBCPP_INLINE_VISIBILITY 1001aed8d94eSDimitry Andric static _Up* 1002aed8d94eSDimitry Andric __operator_arrow(true_type, _Up& __x) 1003aed8d94eSDimitry Andric { 1004aed8d94eSDimitry Andric return _VSTD::addressof(__x); 1005aed8d94eSDimitry Andric } 1006aed8d94eSDimitry Andric 1007aed8d94eSDimitry Andric template <class _Up> 1008aed8d94eSDimitry Andric _LIBCPP_INLINE_VISIBILITY 1009aed8d94eSDimitry Andric static constexpr _Up* 1010aed8d94eSDimitry Andric __operator_arrow(false_type, _Up& __x) 1011aed8d94eSDimitry Andric { 1012aed8d94eSDimitry Andric return &__x; 1013aed8d94eSDimitry Andric } 1014aed8d94eSDimitry Andric}; 1015aed8d94eSDimitry Andric 10164ba319b5SDimitry Andric#ifndef _LIBCPP_HAS_NO_DEDUCTION_GUIDES 10174ba319b5SDimitry Andrictemplate<class T> 10184ba319b5SDimitry Andric optional(T) -> optional<T>; 10194ba319b5SDimitry Andric#endif 10204ba319b5SDimitry Andric 1021aed8d94eSDimitry Andric// Comparisons between optionals 1022540d2a8bSDimitry Andrictemplate <class _Tp, class _Up> 1023aed8d94eSDimitry Andric_LIBCPP_INLINE_VISIBILITY constexpr 1024aed8d94eSDimitry Andricenable_if_t< 1025aed8d94eSDimitry Andric is_convertible_v<decltype(_VSTD::declval<const _Tp&>() == 1026540d2a8bSDimitry Andric _VSTD::declval<const _Up&>()), bool>, 1027aed8d94eSDimitry Andric bool 1028aed8d94eSDimitry Andric> 1029540d2a8bSDimitry Andricoperator==(const optional<_Tp>& __x, const optional<_Up>& __y) 1030aed8d94eSDimitry Andric{ 1031aed8d94eSDimitry Andric if (static_cast<bool>(__x) != static_cast<bool>(__y)) 1032aed8d94eSDimitry Andric return false; 1033aed8d94eSDimitry Andric if (!static_cast<bool>(__x)) 1034aed8d94eSDimitry Andric return true; 1035aed8d94eSDimitry Andric return *__x == *__y; 1036aed8d94eSDimitry Andric} 1037aed8d94eSDimitry Andric 1038540d2a8bSDimitry Andrictemplate <class _Tp, class _Up> 1039aed8d94eSDimitry Andric_LIBCPP_INLINE_VISIBILITY constexpr 1040aed8d94eSDimitry Andricenable_if_t< 1041aed8d94eSDimitry Andric is_convertible_v<decltype(_VSTD::declval<const _Tp&>() != 1042540d2a8bSDimitry Andric _VSTD::declval<const _Up&>()), bool>, 1043aed8d94eSDimitry Andric bool 1044aed8d94eSDimitry Andric> 1045540d2a8bSDimitry Andricoperator!=(const optional<_Tp>& __x, const optional<_Up>& __y) 1046aed8d94eSDimitry Andric{ 1047aed8d94eSDimitry Andric if (static_cast<bool>(__x) != static_cast<bool>(__y)) 1048aed8d94eSDimitry Andric return true; 1049aed8d94eSDimitry Andric if (!static_cast<bool>(__x)) 1050aed8d94eSDimitry Andric return false; 1051aed8d94eSDimitry Andric return *__x != *__y; 1052aed8d94eSDimitry Andric} 1053aed8d94eSDimitry Andric 1054540d2a8bSDimitry Andrictemplate <class _Tp, class _Up> 1055aed8d94eSDimitry Andric_LIBCPP_INLINE_VISIBILITY constexpr 1056aed8d94eSDimitry Andricenable_if_t< 1057aed8d94eSDimitry Andric is_convertible_v<decltype(_VSTD::declval<const _Tp&>() < 1058540d2a8bSDimitry Andric _VSTD::declval<const _Up&>()), bool>, 1059aed8d94eSDimitry Andric bool 1060aed8d94eSDimitry Andric> 1061540d2a8bSDimitry Andricoperator<(const optional<_Tp>& __x, const optional<_Up>& __y) 1062aed8d94eSDimitry Andric{ 1063aed8d94eSDimitry Andric if (!static_cast<bool>(__y)) 1064aed8d94eSDimitry Andric return false; 1065aed8d94eSDimitry Andric if (!static_cast<bool>(__x)) 1066aed8d94eSDimitry Andric return true; 1067aed8d94eSDimitry Andric return *__x < *__y; 1068aed8d94eSDimitry Andric} 1069aed8d94eSDimitry Andric 1070540d2a8bSDimitry Andrictemplate <class _Tp, class _Up> 1071aed8d94eSDimitry Andric_LIBCPP_INLINE_VISIBILITY constexpr 1072aed8d94eSDimitry Andricenable_if_t< 1073aed8d94eSDimitry Andric is_convertible_v<decltype(_VSTD::declval<const _Tp&>() > 1074540d2a8bSDimitry Andric _VSTD::declval<const _Up&>()), bool>, 1075aed8d94eSDimitry Andric bool 1076aed8d94eSDimitry Andric> 1077540d2a8bSDimitry Andricoperator>(const optional<_Tp>& __x, const optional<_Up>& __y) 1078aed8d94eSDimitry Andric{ 1079aed8d94eSDimitry Andric if (!static_cast<bool>(__x)) 1080aed8d94eSDimitry Andric return false; 1081aed8d94eSDimitry Andric if (!static_cast<bool>(__y)) 1082aed8d94eSDimitry Andric return true; 1083aed8d94eSDimitry Andric return *__x > *__y; 1084aed8d94eSDimitry Andric} 1085aed8d94eSDimitry Andric 1086540d2a8bSDimitry Andrictemplate <class _Tp, class _Up> 1087aed8d94eSDimitry Andric_LIBCPP_INLINE_VISIBILITY constexpr 1088aed8d94eSDimitry Andricenable_if_t< 1089aed8d94eSDimitry Andric is_convertible_v<decltype(_VSTD::declval<const _Tp&>() <= 1090540d2a8bSDimitry Andric _VSTD::declval<const _Up&>()), bool>, 1091aed8d94eSDimitry Andric bool 1092aed8d94eSDimitry Andric> 1093540d2a8bSDimitry Andricoperator<=(const optional<_Tp>& __x, const optional<_Up>& __y) 1094aed8d94eSDimitry Andric{ 1095aed8d94eSDimitry Andric if (!static_cast<bool>(__x)) 1096aed8d94eSDimitry Andric return true; 1097aed8d94eSDimitry Andric if (!static_cast<bool>(__y)) 1098aed8d94eSDimitry Andric return false; 1099aed8d94eSDimitry Andric return *__x <= *__y; 1100aed8d94eSDimitry Andric} 1101aed8d94eSDimitry Andric 1102540d2a8bSDimitry Andrictemplate <class _Tp, class _Up> 1103aed8d94eSDimitry Andric_LIBCPP_INLINE_VISIBILITY constexpr 1104aed8d94eSDimitry Andricenable_if_t< 1105aed8d94eSDimitry Andric is_convertible_v<decltype(_VSTD::declval<const _Tp&>() >= 1106540d2a8bSDimitry Andric _VSTD::declval<const _Up&>()), bool>, 1107aed8d94eSDimitry Andric bool 1108aed8d94eSDimitry Andric> 1109540d2a8bSDimitry Andricoperator>=(const optional<_Tp>& __x, const optional<_Up>& __y) 1110aed8d94eSDimitry Andric{ 1111aed8d94eSDimitry Andric if (!static_cast<bool>(__y)) 1112aed8d94eSDimitry Andric return true; 1113aed8d94eSDimitry Andric if (!static_cast<bool>(__x)) 1114aed8d94eSDimitry Andric return false; 1115aed8d94eSDimitry Andric return *__x >= *__y; 1116aed8d94eSDimitry Andric} 1117aed8d94eSDimitry Andric 1118aed8d94eSDimitry Andric// Comparisons with nullopt 1119aed8d94eSDimitry Andrictemplate <class _Tp> 1120aed8d94eSDimitry Andric_LIBCPP_INLINE_VISIBILITY constexpr 1121aed8d94eSDimitry Andricbool 1122aed8d94eSDimitry Andricoperator==(const optional<_Tp>& __x, nullopt_t) noexcept 1123aed8d94eSDimitry Andric{ 1124aed8d94eSDimitry Andric return !static_cast<bool>(__x); 1125aed8d94eSDimitry Andric} 1126aed8d94eSDimitry Andric 1127aed8d94eSDimitry Andrictemplate <class _Tp> 1128aed8d94eSDimitry Andric_LIBCPP_INLINE_VISIBILITY constexpr 1129aed8d94eSDimitry Andricbool 1130aed8d94eSDimitry Andricoperator==(nullopt_t, const optional<_Tp>& __x) noexcept 1131aed8d94eSDimitry Andric{ 1132aed8d94eSDimitry Andric return !static_cast<bool>(__x); 1133aed8d94eSDimitry Andric} 1134aed8d94eSDimitry Andric 1135aed8d94eSDimitry Andrictemplate <class _Tp> 1136aed8d94eSDimitry Andric_LIBCPP_INLINE_VISIBILITY constexpr 1137aed8d94eSDimitry Andricbool 1138aed8d94eSDimitry Andricoperator!=(const optional<_Tp>& __x, nullopt_t) noexcept 1139aed8d94eSDimitry Andric{ 1140aed8d94eSDimitry Andric return static_cast<bool>(__x); 1141aed8d94eSDimitry Andric} 1142aed8d94eSDimitry Andric 1143aed8d94eSDimitry Andrictemplate <class _Tp> 1144aed8d94eSDimitry Andric_LIBCPP_INLINE_VISIBILITY constexpr 1145aed8d94eSDimitry Andricbool 1146aed8d94eSDimitry Andricoperator!=(nullopt_t, const optional<_Tp>& __x) noexcept 1147aed8d94eSDimitry Andric{ 1148aed8d94eSDimitry Andric return static_cast<bool>(__x); 1149aed8d94eSDimitry Andric} 1150aed8d94eSDimitry Andric 1151aed8d94eSDimitry Andrictemplate <class _Tp> 1152aed8d94eSDimitry Andric_LIBCPP_INLINE_VISIBILITY constexpr 1153aed8d94eSDimitry Andricbool 1154aed8d94eSDimitry Andricoperator<(const optional<_Tp>&, nullopt_t) noexcept 1155aed8d94eSDimitry Andric{ 1156aed8d94eSDimitry Andric return false; 1157aed8d94eSDimitry Andric} 1158aed8d94eSDimitry Andric 1159aed8d94eSDimitry Andrictemplate <class _Tp> 1160aed8d94eSDimitry Andric_LIBCPP_INLINE_VISIBILITY constexpr 1161aed8d94eSDimitry Andricbool 1162aed8d94eSDimitry Andricoperator<(nullopt_t, const optional<_Tp>& __x) noexcept 1163aed8d94eSDimitry Andric{ 1164aed8d94eSDimitry Andric return static_cast<bool>(__x); 1165aed8d94eSDimitry Andric} 1166aed8d94eSDimitry Andric 1167aed8d94eSDimitry Andrictemplate <class _Tp> 1168aed8d94eSDimitry Andric_LIBCPP_INLINE_VISIBILITY constexpr 1169aed8d94eSDimitry Andricbool 1170aed8d94eSDimitry Andricoperator<=(const optional<_Tp>& __x, nullopt_t) noexcept 1171aed8d94eSDimitry Andric{ 1172aed8d94eSDimitry Andric return !static_cast<bool>(__x); 1173aed8d94eSDimitry Andric} 1174aed8d94eSDimitry Andric 1175aed8d94eSDimitry Andrictemplate <class _Tp> 1176aed8d94eSDimitry Andric_LIBCPP_INLINE_VISIBILITY constexpr 1177aed8d94eSDimitry Andricbool 1178aed8d94eSDimitry Andricoperator<=(nullopt_t, const optional<_Tp>&) noexcept 1179aed8d94eSDimitry Andric{ 1180aed8d94eSDimitry Andric return true; 1181aed8d94eSDimitry Andric} 1182aed8d94eSDimitry Andric 1183aed8d94eSDimitry Andrictemplate <class _Tp> 1184aed8d94eSDimitry Andric_LIBCPP_INLINE_VISIBILITY constexpr 1185aed8d94eSDimitry Andricbool 1186aed8d94eSDimitry Andricoperator>(const optional<_Tp>& __x, nullopt_t) noexcept 1187aed8d94eSDimitry Andric{ 1188aed8d94eSDimitry Andric return static_cast<bool>(__x); 1189aed8d94eSDimitry Andric} 1190aed8d94eSDimitry Andric 1191aed8d94eSDimitry Andrictemplate <class _Tp> 1192aed8d94eSDimitry Andric_LIBCPP_INLINE_VISIBILITY constexpr 1193aed8d94eSDimitry Andricbool 1194aed8d94eSDimitry Andricoperator>(nullopt_t, const optional<_Tp>&) noexcept 1195aed8d94eSDimitry Andric{ 1196aed8d94eSDimitry Andric return false; 1197aed8d94eSDimitry Andric} 1198aed8d94eSDimitry Andric 1199aed8d94eSDimitry Andrictemplate <class _Tp> 1200aed8d94eSDimitry Andric_LIBCPP_INLINE_VISIBILITY constexpr 1201aed8d94eSDimitry Andricbool 1202aed8d94eSDimitry Andricoperator>=(const optional<_Tp>&, nullopt_t) noexcept 1203aed8d94eSDimitry Andric{ 1204aed8d94eSDimitry Andric return true; 1205aed8d94eSDimitry Andric} 1206aed8d94eSDimitry Andric 1207aed8d94eSDimitry Andrictemplate <class _Tp> 1208aed8d94eSDimitry Andric_LIBCPP_INLINE_VISIBILITY constexpr 1209aed8d94eSDimitry Andricbool 1210aed8d94eSDimitry Andricoperator>=(nullopt_t, const optional<_Tp>& __x) noexcept 1211aed8d94eSDimitry Andric{ 1212aed8d94eSDimitry Andric return !static_cast<bool>(__x); 1213aed8d94eSDimitry Andric} 1214aed8d94eSDimitry Andric 1215aed8d94eSDimitry Andric// Comparisons with T 1216540d2a8bSDimitry Andrictemplate <class _Tp, class _Up> 1217aed8d94eSDimitry Andric_LIBCPP_INLINE_VISIBILITY constexpr 1218aed8d94eSDimitry Andricenable_if_t< 1219aed8d94eSDimitry Andric is_convertible_v<decltype(_VSTD::declval<const _Tp&>() == 1220540d2a8bSDimitry Andric _VSTD::declval<const _Up&>()), bool>, 1221aed8d94eSDimitry Andric bool 1222aed8d94eSDimitry Andric> 1223540d2a8bSDimitry Andricoperator==(const optional<_Tp>& __x, const _Up& __v) 1224aed8d94eSDimitry Andric{ 1225aed8d94eSDimitry Andric return static_cast<bool>(__x) ? *__x == __v : false; 1226aed8d94eSDimitry Andric} 1227aed8d94eSDimitry Andric 1228540d2a8bSDimitry Andrictemplate <class _Tp, class _Up> 1229aed8d94eSDimitry Andric_LIBCPP_INLINE_VISIBILITY constexpr 1230aed8d94eSDimitry Andricenable_if_t< 1231aed8d94eSDimitry Andric is_convertible_v<decltype(_VSTD::declval<const _Tp&>() == 1232540d2a8bSDimitry Andric _VSTD::declval<const _Up&>()), bool>, 1233aed8d94eSDimitry Andric bool 1234aed8d94eSDimitry Andric> 1235540d2a8bSDimitry Andricoperator==(const _Tp& __v, const optional<_Up>& __x) 1236aed8d94eSDimitry Andric{ 1237aed8d94eSDimitry Andric return static_cast<bool>(__x) ? __v == *__x : false; 1238aed8d94eSDimitry Andric} 1239aed8d94eSDimitry Andric 1240540d2a8bSDimitry Andrictemplate <class _Tp, class _Up> 1241aed8d94eSDimitry Andric_LIBCPP_INLINE_VISIBILITY constexpr 1242aed8d94eSDimitry Andricenable_if_t< 1243aed8d94eSDimitry Andric is_convertible_v<decltype(_VSTD::declval<const _Tp&>() != 1244540d2a8bSDimitry Andric _VSTD::declval<const _Up&>()), bool>, 1245aed8d94eSDimitry Andric bool 1246aed8d94eSDimitry Andric> 1247540d2a8bSDimitry Andricoperator!=(const optional<_Tp>& __x, const _Up& __v) 1248aed8d94eSDimitry Andric{ 1249aed8d94eSDimitry Andric return static_cast<bool>(__x) ? *__x != __v : true; 1250aed8d94eSDimitry Andric} 1251aed8d94eSDimitry Andric 1252540d2a8bSDimitry Andrictemplate <class _Tp, class _Up> 1253aed8d94eSDimitry Andric_LIBCPP_INLINE_VISIBILITY constexpr 1254aed8d94eSDimitry Andricenable_if_t< 1255aed8d94eSDimitry Andric is_convertible_v<decltype(_VSTD::declval<const _Tp&>() != 1256540d2a8bSDimitry Andric _VSTD::declval<const _Up&>()), bool>, 1257aed8d94eSDimitry Andric bool 1258aed8d94eSDimitry Andric> 1259540d2a8bSDimitry Andricoperator!=(const _Tp& __v, const optional<_Up>& __x) 1260aed8d94eSDimitry Andric{ 1261aed8d94eSDimitry Andric return static_cast<bool>(__x) ? __v != *__x : true; 1262aed8d94eSDimitry Andric} 1263aed8d94eSDimitry Andric 1264540d2a8bSDimitry Andrictemplate <class _Tp, class _Up> 1265aed8d94eSDimitry Andric_LIBCPP_INLINE_VISIBILITY constexpr 1266aed8d94eSDimitry Andricenable_if_t< 1267aed8d94eSDimitry Andric is_convertible_v<decltype(_VSTD::declval<const _Tp&>() < 1268540d2a8bSDimitry Andric _VSTD::declval<const _Up&>()), bool>, 1269aed8d94eSDimitry Andric bool 1270aed8d94eSDimitry Andric> 1271540d2a8bSDimitry Andricoperator<(const optional<_Tp>& __x, const _Up& __v) 1272aed8d94eSDimitry Andric{ 1273aed8d94eSDimitry Andric return static_cast<bool>(__x) ? *__x < __v : true; 1274aed8d94eSDimitry Andric} 1275aed8d94eSDimitry Andric 1276540d2a8bSDimitry Andrictemplate <class _Tp, class _Up> 1277aed8d94eSDimitry Andric_LIBCPP_INLINE_VISIBILITY constexpr 1278aed8d94eSDimitry Andricenable_if_t< 1279aed8d94eSDimitry Andric is_convertible_v<decltype(_VSTD::declval<const _Tp&>() < 1280540d2a8bSDimitry Andric _VSTD::declval<const _Up&>()), bool>, 1281aed8d94eSDimitry Andric bool 1282aed8d94eSDimitry Andric> 1283540d2a8bSDimitry Andricoperator<(const _Tp& __v, const optional<_Up>& __x) 1284aed8d94eSDimitry Andric{ 1285aed8d94eSDimitry Andric return static_cast<bool>(__x) ? __v < *__x : false; 1286aed8d94eSDimitry Andric} 1287aed8d94eSDimitry Andric 1288540d2a8bSDimitry Andrictemplate <class _Tp, class _Up> 1289aed8d94eSDimitry Andric_LIBCPP_INLINE_VISIBILITY constexpr 1290aed8d94eSDimitry Andricenable_if_t< 1291aed8d94eSDimitry Andric is_convertible_v<decltype(_VSTD::declval<const _Tp&>() <= 1292540d2a8bSDimitry Andric _VSTD::declval<const _Up&>()), bool>, 1293aed8d94eSDimitry Andric bool 1294aed8d94eSDimitry Andric> 1295540d2a8bSDimitry Andricoperator<=(const optional<_Tp>& __x, const _Up& __v) 1296aed8d94eSDimitry Andric{ 1297aed8d94eSDimitry Andric return static_cast<bool>(__x) ? *__x <= __v : true; 1298aed8d94eSDimitry Andric} 1299aed8d94eSDimitry Andric 1300540d2a8bSDimitry Andrictemplate <class _Tp, class _Up> 1301aed8d94eSDimitry Andric_LIBCPP_INLINE_VISIBILITY constexpr 1302aed8d94eSDimitry Andricenable_if_t< 1303aed8d94eSDimitry Andric is_convertible_v<decltype(_VSTD::declval<const _Tp&>() <= 1304540d2a8bSDimitry Andric _VSTD::declval<const _Up&>()), bool>, 1305aed8d94eSDimitry Andric bool 1306aed8d94eSDimitry Andric> 1307540d2a8bSDimitry Andricoperator<=(const _Tp& __v, const optional<_Up>& __x) 1308aed8d94eSDimitry Andric{ 1309aed8d94eSDimitry Andric return static_cast<bool>(__x) ? __v <= *__x : false; 1310aed8d94eSDimitry Andric} 1311aed8d94eSDimitry Andric 1312540d2a8bSDimitry Andrictemplate <class _Tp, class _Up> 1313aed8d94eSDimitry Andric_LIBCPP_INLINE_VISIBILITY constexpr 1314aed8d94eSDimitry Andricenable_if_t< 1315aed8d94eSDimitry Andric is_convertible_v<decltype(_VSTD::declval<const _Tp&>() > 1316540d2a8bSDimitry Andric _VSTD::declval<const _Up&>()), bool>, 1317aed8d94eSDimitry Andric bool 1318aed8d94eSDimitry Andric> 1319540d2a8bSDimitry Andricoperator>(const optional<_Tp>& __x, const _Up& __v) 1320aed8d94eSDimitry Andric{ 1321aed8d94eSDimitry Andric return static_cast<bool>(__x) ? *__x > __v : false; 1322aed8d94eSDimitry Andric} 1323aed8d94eSDimitry Andric 1324540d2a8bSDimitry Andrictemplate <class _Tp, class _Up> 1325aed8d94eSDimitry Andric_LIBCPP_INLINE_VISIBILITY constexpr 1326aed8d94eSDimitry Andricenable_if_t< 1327aed8d94eSDimitry Andric is_convertible_v<decltype(_VSTD::declval<const _Tp&>() > 1328540d2a8bSDimitry Andric _VSTD::declval<const _Up&>()), bool>, 1329aed8d94eSDimitry Andric bool 1330aed8d94eSDimitry Andric> 1331540d2a8bSDimitry Andricoperator>(const _Tp& __v, const optional<_Up>& __x) 1332aed8d94eSDimitry Andric{ 1333aed8d94eSDimitry Andric return static_cast<bool>(__x) ? __v > *__x : true; 1334aed8d94eSDimitry Andric} 1335aed8d94eSDimitry Andric 1336540d2a8bSDimitry Andrictemplate <class _Tp, class _Up> 1337aed8d94eSDimitry Andric_LIBCPP_INLINE_VISIBILITY constexpr 1338aed8d94eSDimitry Andricenable_if_t< 1339aed8d94eSDimitry Andric is_convertible_v<decltype(_VSTD::declval<const _Tp&>() >= 1340540d2a8bSDimitry Andric _VSTD::declval<const _Up&>()), bool>, 1341aed8d94eSDimitry Andric bool 1342aed8d94eSDimitry Andric> 1343540d2a8bSDimitry Andricoperator>=(const optional<_Tp>& __x, const _Up& __v) 1344aed8d94eSDimitry Andric{ 1345aed8d94eSDimitry Andric return static_cast<bool>(__x) ? *__x >= __v : false; 1346aed8d94eSDimitry Andric} 1347aed8d94eSDimitry Andric 1348540d2a8bSDimitry Andrictemplate <class _Tp, class _Up> 1349aed8d94eSDimitry Andric_LIBCPP_INLINE_VISIBILITY constexpr 1350aed8d94eSDimitry Andricenable_if_t< 1351aed8d94eSDimitry Andric is_convertible_v<decltype(_VSTD::declval<const _Tp&>() >= 1352540d2a8bSDimitry Andric _VSTD::declval<const _Up&>()), bool>, 1353aed8d94eSDimitry Andric bool 1354aed8d94eSDimitry Andric> 1355540d2a8bSDimitry Andricoperator>=(const _Tp& __v, const optional<_Up>& __x) 1356aed8d94eSDimitry Andric{ 1357aed8d94eSDimitry Andric return static_cast<bool>(__x) ? __v >= *__x : true; 1358aed8d94eSDimitry Andric} 1359aed8d94eSDimitry Andric 1360aed8d94eSDimitry Andric 1361aed8d94eSDimitry Andrictemplate <class _Tp> 1362aed8d94eSDimitry Andricinline _LIBCPP_INLINE_VISIBILITY 1363aed8d94eSDimitry Andricenable_if_t< 1364aed8d94eSDimitry Andric is_move_constructible_v<_Tp> && is_swappable_v<_Tp>, 1365aed8d94eSDimitry Andric void 1366aed8d94eSDimitry Andric> 1367aed8d94eSDimitry Andricswap(optional<_Tp>& __x, optional<_Tp>& __y) noexcept(noexcept(__x.swap(__y))) 1368aed8d94eSDimitry Andric{ 1369aed8d94eSDimitry Andric __x.swap(__y); 1370aed8d94eSDimitry Andric} 1371aed8d94eSDimitry Andric 1372aed8d94eSDimitry Andrictemplate <class _Tp> 1373aed8d94eSDimitry Andric_LIBCPP_INLINE_VISIBILITY constexpr 1374aed8d94eSDimitry Andricoptional<decay_t<_Tp>> make_optional(_Tp&& __v) 1375aed8d94eSDimitry Andric{ 1376aed8d94eSDimitry Andric return optional<decay_t<_Tp>>(_VSTD::forward<_Tp>(__v)); 1377aed8d94eSDimitry Andric} 1378aed8d94eSDimitry Andric 1379aed8d94eSDimitry Andrictemplate <class _Tp, class... _Args> 1380aed8d94eSDimitry Andric_LIBCPP_INLINE_VISIBILITY constexpr 1381aed8d94eSDimitry Andricoptional<_Tp> make_optional(_Args&&... __args) 1382aed8d94eSDimitry Andric{ 1383aed8d94eSDimitry Andric return optional<_Tp>(in_place, _VSTD::forward<_Args>(__args)...); 1384aed8d94eSDimitry Andric} 1385aed8d94eSDimitry Andric 1386aed8d94eSDimitry Andrictemplate <class _Tp, class _Up, class... _Args> 1387aed8d94eSDimitry Andric_LIBCPP_INLINE_VISIBILITY constexpr 1388aed8d94eSDimitry Andricoptional<_Tp> make_optional(initializer_list<_Up> __il, _Args&&... __args) 1389aed8d94eSDimitry Andric{ 1390aed8d94eSDimitry Andric return optional<_Tp>(in_place, __il, _VSTD::forward<_Args>(__args)...); 1391aed8d94eSDimitry Andric} 1392aed8d94eSDimitry Andric 1393aed8d94eSDimitry Andrictemplate <class _Tp> 1394540d2a8bSDimitry Andricstruct _LIBCPP_TEMPLATE_VIS hash< 1395540d2a8bSDimitry Andric __enable_hash_helper<optional<_Tp>, remove_const_t<_Tp>> 1396540d2a8bSDimitry Andric> 1397aed8d94eSDimitry Andric{ 1398aed8d94eSDimitry Andric typedef optional<_Tp> argument_type; 1399aed8d94eSDimitry Andric typedef size_t result_type; 1400aed8d94eSDimitry Andric 1401aed8d94eSDimitry Andric _LIBCPP_INLINE_VISIBILITY 1402540d2a8bSDimitry Andric result_type operator()(const argument_type& __opt) const 1403aed8d94eSDimitry Andric { 1404540d2a8bSDimitry Andric return static_cast<bool>(__opt) ? hash<remove_const_t<_Tp>>()(*__opt) : 0; 1405aed8d94eSDimitry Andric } 1406aed8d94eSDimitry Andric}; 1407aed8d94eSDimitry Andric 1408aed8d94eSDimitry Andric_LIBCPP_END_NAMESPACE_STD 1409aed8d94eSDimitry Andric 1410aed8d94eSDimitry Andric#endif // _LIBCPP_STD_VER > 14 1411aed8d94eSDimitry Andric 1412f9448bf3SDimitry Andric_LIBCPP_POP_MACROS 1413f9448bf3SDimitry Andric 1414aed8d94eSDimitry Andric#endif // _LIBCPP_OPTIONAL 1415