10b57cec5SDimitry Andric// -*- C++ -*- 20b57cec5SDimitry Andric//===-------------------------- optional ----------------------------------===// 30b57cec5SDimitry Andric// 40b57cec5SDimitry Andric// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 50b57cec5SDimitry Andric// See https://llvm.org/LICENSE.txt for license information. 60b57cec5SDimitry Andric// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 70b57cec5SDimitry Andric// 80b57cec5SDimitry Andric//===----------------------------------------------------------------------===// 90b57cec5SDimitry Andric 100b57cec5SDimitry Andric#ifndef _LIBCPP_OPTIONAL 110b57cec5SDimitry Andric#define _LIBCPP_OPTIONAL 120b57cec5SDimitry Andric 130b57cec5SDimitry Andric/* 140b57cec5SDimitry Andric optional synopsis 150b57cec5SDimitry Andric 160b57cec5SDimitry Andric// C++1z 170b57cec5SDimitry Andric 180b57cec5SDimitry Andricnamespace std { 190b57cec5SDimitry Andric // 23.6.3, optional for object types 200b57cec5SDimitry Andric template <class T> class optional; 210b57cec5SDimitry Andric 220b57cec5SDimitry Andric // 23.6.4, no-value state indicator 230b57cec5SDimitry Andric struct nullopt_t{see below }; 240b57cec5SDimitry Andric inline constexpr nullopt_t nullopt(unspecified ); 250b57cec5SDimitry Andric 260b57cec5SDimitry Andric // 23.6.5, class bad_optional_access 270b57cec5SDimitry Andric class bad_optional_access; 280b57cec5SDimitry Andric 290b57cec5SDimitry Andric // 23.6.6, relational operators 300b57cec5SDimitry Andric template <class T, class U> 310b57cec5SDimitry Andric constexpr bool operator==(const optional<T>&, const optional<U>&); 320b57cec5SDimitry Andric template <class T, class U> 330b57cec5SDimitry Andric constexpr bool operator!=(const optional<T>&, const optional<U>&); 340b57cec5SDimitry Andric template <class T, class U> 350b57cec5SDimitry Andric constexpr bool operator<(const optional<T>&, const optional<U>&); 360b57cec5SDimitry Andric template <class T, class U> 370b57cec5SDimitry Andric constexpr bool operator>(const optional<T>&, const optional<U>&); 380b57cec5SDimitry Andric template <class T, class U> 390b57cec5SDimitry Andric constexpr bool operator<=(const optional<T>&, const optional<U>&); 400b57cec5SDimitry Andric template <class T, class U> 410b57cec5SDimitry Andric constexpr bool operator>=(const optional<T>&, const optional<U>&); 420b57cec5SDimitry Andric 430b57cec5SDimitry Andric // 23.6.7 comparison with nullopt 440b57cec5SDimitry Andric template <class T> constexpr bool operator==(const optional<T>&, nullopt_t) noexcept; 450b57cec5SDimitry Andric template <class T> constexpr bool operator==(nullopt_t, const optional<T>&) noexcept; 460b57cec5SDimitry Andric template <class T> constexpr bool operator!=(const optional<T>&, nullopt_t) noexcept; 470b57cec5SDimitry Andric template <class T> constexpr bool operator!=(nullopt_t, const optional<T>&) noexcept; 480b57cec5SDimitry Andric template <class T> constexpr bool operator<(const optional<T>&, nullopt_t) noexcept; 490b57cec5SDimitry Andric template <class T> constexpr bool operator<(nullopt_t, const optional<T>&) noexcept; 500b57cec5SDimitry Andric template <class T> constexpr bool operator<=(const optional<T>&, nullopt_t) noexcept; 510b57cec5SDimitry Andric template <class T> constexpr bool operator<=(nullopt_t, const optional<T>&) noexcept; 520b57cec5SDimitry Andric template <class T> constexpr bool operator>(const optional<T>&, nullopt_t) noexcept; 530b57cec5SDimitry Andric template <class T> constexpr bool operator>(nullopt_t, const optional<T>&) noexcept; 540b57cec5SDimitry Andric template <class T> constexpr bool operator>=(const optional<T>&, nullopt_t) noexcept; 550b57cec5SDimitry Andric template <class T> constexpr bool operator>=(nullopt_t, const optional<T>&) noexcept; 560b57cec5SDimitry Andric 570b57cec5SDimitry Andric // 23.6.8, comparison with T 580b57cec5SDimitry Andric template <class T, class U> constexpr bool operator==(const optional<T>&, const U&); 590b57cec5SDimitry Andric template <class T, class U> constexpr bool operator==(const T&, const optional<U>&); 600b57cec5SDimitry Andric template <class T, class U> constexpr bool operator!=(const optional<T>&, const U&); 610b57cec5SDimitry Andric template <class T, class U> constexpr bool operator!=(const T&, const optional<U>&); 620b57cec5SDimitry Andric template <class T, class U> constexpr bool operator<(const optional<T>&, const U&); 630b57cec5SDimitry Andric template <class T, class U> constexpr bool operator<(const T&, const optional<U>&); 640b57cec5SDimitry Andric template <class T, class U> constexpr bool operator<=(const optional<T>&, const U&); 650b57cec5SDimitry Andric template <class T, class U> constexpr bool operator<=(const T&, const optional<U>&); 660b57cec5SDimitry Andric template <class T, class U> constexpr bool operator>(const optional<T>&, const U&); 670b57cec5SDimitry Andric template <class T, class U> constexpr bool operator>(const T&, const optional<U>&); 680b57cec5SDimitry Andric template <class T, class U> constexpr bool operator>=(const optional<T>&, const U&); 690b57cec5SDimitry Andric template <class T, class U> constexpr bool operator>=(const T&, const optional<U>&); 700b57cec5SDimitry Andric 710b57cec5SDimitry Andric // 23.6.9, specialized algorithms 720b57cec5SDimitry Andric template <class T> void swap(optional<T>&, optional<T>&) noexcept(see below ); 730b57cec5SDimitry Andric template <class T> constexpr optional<see below > make_optional(T&&); 740b57cec5SDimitry Andric template <class T, class... Args> 750b57cec5SDimitry Andric constexpr optional<T> make_optional(Args&&... args); 760b57cec5SDimitry Andric template <class T, class U, class... Args> 770b57cec5SDimitry Andric constexpr optional<T> make_optional(initializer_list<U> il, Args&&... args); 780b57cec5SDimitry Andric 790b57cec5SDimitry Andric // 23.6.10, hash support 800b57cec5SDimitry Andric template <class T> struct hash; 810b57cec5SDimitry Andric template <class T> struct hash<optional<T>>; 820b57cec5SDimitry Andric 830b57cec5SDimitry Andric template <class T> class optional { 840b57cec5SDimitry Andric public: 850b57cec5SDimitry Andric using value_type = T; 860b57cec5SDimitry Andric 870b57cec5SDimitry Andric // 23.6.3.1, constructors 880b57cec5SDimitry Andric constexpr optional() noexcept; 890b57cec5SDimitry Andric constexpr optional(nullopt_t) noexcept; 900b57cec5SDimitry Andric optional(const optional &); 910b57cec5SDimitry Andric optional(optional &&) noexcept(see below); 920b57cec5SDimitry Andric template <class... Args> constexpr explicit optional(in_place_t, Args &&...); 930b57cec5SDimitry Andric template <class U, class... Args> 940b57cec5SDimitry Andric constexpr explicit optional(in_place_t, initializer_list<U>, Args &&...); 950b57cec5SDimitry Andric template <class U = T> 960b57cec5SDimitry Andric constexpr EXPLICIT optional(U &&); 970b57cec5SDimitry Andric template <class U> 980b57cec5SDimitry Andric constexpr EXPLICIT optional(const optional<U> &); 990b57cec5SDimitry Andric template <class U> 1000b57cec5SDimitry Andric constexpr EXPLICIT optional(optional<U> &&); 1010b57cec5SDimitry Andric 1020b57cec5SDimitry Andric // 23.6.3.2, destructor 1030b57cec5SDimitry Andric ~optional(); 1040b57cec5SDimitry Andric 1050b57cec5SDimitry Andric // 23.6.3.3, assignment 1060b57cec5SDimitry Andric optional &operator=(nullopt_t) noexcept; 1070b57cec5SDimitry Andric optional &operator=(const optional &); // constexpr in C++20 1080b57cec5SDimitry Andric optional &operator=(optional &&) noexcept(see below); // constexpr in C++20 1090b57cec5SDimitry Andric template <class U = T> optional &operator=(U &&); 1100b57cec5SDimitry Andric template <class U> optional &operator=(const optional<U> &); 1110b57cec5SDimitry Andric template <class U> optional &operator=(optional<U> &&); 1120b57cec5SDimitry Andric template <class... Args> T& emplace(Args &&...); 1130b57cec5SDimitry Andric template <class U, class... Args> 1140b57cec5SDimitry Andric T& emplace(initializer_list<U>, Args &&...); 1150b57cec5SDimitry Andric 1160b57cec5SDimitry Andric // 23.6.3.4, swap 1170b57cec5SDimitry Andric void swap(optional &) noexcept(see below ); 1180b57cec5SDimitry Andric 1190b57cec5SDimitry Andric // 23.6.3.5, observers 1200b57cec5SDimitry Andric constexpr T const *operator->() const; 1210b57cec5SDimitry Andric constexpr T *operator->(); 1220b57cec5SDimitry Andric constexpr T const &operator*() const &; 1230b57cec5SDimitry Andric constexpr T &operator*() &; 1240b57cec5SDimitry Andric constexpr T &&operator*() &&; 1250b57cec5SDimitry Andric constexpr const T &&operator*() const &&; 1260b57cec5SDimitry Andric constexpr explicit operator bool() const noexcept; 1270b57cec5SDimitry Andric constexpr bool has_value() const noexcept; 1280b57cec5SDimitry Andric constexpr T const &value() const &; 1290b57cec5SDimitry Andric constexpr T &value() &; 1300b57cec5SDimitry Andric constexpr T &&value() &&; 1310b57cec5SDimitry Andric constexpr const T &&value() const &&; 1320b57cec5SDimitry Andric template <class U> constexpr T value_or(U &&) const &; 1330b57cec5SDimitry Andric template <class U> constexpr T value_or(U &&) &&; 1340b57cec5SDimitry Andric 1350b57cec5SDimitry Andric // 23.6.3.6, modifiers 1360b57cec5SDimitry Andric void reset() noexcept; 1370b57cec5SDimitry Andric 1380b57cec5SDimitry Andric private: 1390b57cec5SDimitry Andric T *val; // exposition only 1400b57cec5SDimitry Andric }; 1410b57cec5SDimitry Andric 1420b57cec5SDimitry Andrictemplate<class T> 1430b57cec5SDimitry Andric optional(T) -> optional<T>; 1440b57cec5SDimitry Andric 1450b57cec5SDimitry Andric} // namespace std 1460b57cec5SDimitry Andric 1470b57cec5SDimitry Andric*/ 1480b57cec5SDimitry Andric 1490b57cec5SDimitry Andric#include <__config> 150*e8d8bef9SDimitry Andric#include <__availability> 1510b57cec5SDimitry Andric#include <__debug> 1520b57cec5SDimitry Andric#include <__functional_base> 1530b57cec5SDimitry Andric#include <functional> 1540b57cec5SDimitry Andric#include <initializer_list> 1550b57cec5SDimitry Andric#include <new> 1560b57cec5SDimitry Andric#include <stdexcept> 1570b57cec5SDimitry Andric#include <type_traits> 1580b57cec5SDimitry Andric#include <utility> 1590b57cec5SDimitry Andric#include <version> 1600b57cec5SDimitry Andric 1610b57cec5SDimitry Andric#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 1620b57cec5SDimitry Andric#pragma GCC system_header 1630b57cec5SDimitry Andric#endif 1640b57cec5SDimitry Andric 1650b57cec5SDimitry Andric_LIBCPP_PUSH_MACROS 1660b57cec5SDimitry Andric#include <__undef_macros> 1670b57cec5SDimitry Andric 1680b57cec5SDimitry Andric 1690b57cec5SDimitry Andricnamespace std // purposefully not using versioning namespace 1700b57cec5SDimitry Andric{ 1710b57cec5SDimitry Andric 1720b57cec5SDimitry Andricclass _LIBCPP_EXCEPTION_ABI _LIBCPP_AVAILABILITY_BAD_OPTIONAL_ACCESS bad_optional_access 1730b57cec5SDimitry Andric : public exception 1740b57cec5SDimitry Andric{ 1750b57cec5SDimitry Andricpublic: 1760b57cec5SDimitry Andric // Get the key function ~bad_optional_access() into the dylib 1770b57cec5SDimitry Andric virtual ~bad_optional_access() _NOEXCEPT; 1780b57cec5SDimitry Andric virtual const char* what() const _NOEXCEPT; 1790b57cec5SDimitry Andric}; 1800b57cec5SDimitry Andric 1810b57cec5SDimitry Andric} // std 1820b57cec5SDimitry Andric 1830b57cec5SDimitry Andric#if _LIBCPP_STD_VER > 14 1840b57cec5SDimitry Andric 1850b57cec5SDimitry Andric_LIBCPP_BEGIN_NAMESPACE_STD 1860b57cec5SDimitry Andric 1870b57cec5SDimitry Andric_LIBCPP_NORETURN 1880b57cec5SDimitry Andricinline _LIBCPP_INLINE_VISIBILITY 1890b57cec5SDimitry Andric_LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS 1900b57cec5SDimitry Andricvoid __throw_bad_optional_access() { 1910b57cec5SDimitry Andric#ifndef _LIBCPP_NO_EXCEPTIONS 1920b57cec5SDimitry Andric throw bad_optional_access(); 1930b57cec5SDimitry Andric#else 1940b57cec5SDimitry Andric _VSTD::abort(); 1950b57cec5SDimitry Andric#endif 1960b57cec5SDimitry Andric} 1970b57cec5SDimitry Andric 1980b57cec5SDimitry Andricstruct nullopt_t 1990b57cec5SDimitry Andric{ 2000b57cec5SDimitry Andric struct __secret_tag { _LIBCPP_INLINE_VISIBILITY explicit __secret_tag() = default; }; 2010b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY constexpr explicit nullopt_t(__secret_tag, __secret_tag) noexcept {} 2020b57cec5SDimitry Andric}; 2030b57cec5SDimitry Andric 2040b57cec5SDimitry Andric_LIBCPP_INLINE_VAR constexpr nullopt_t nullopt{nullopt_t::__secret_tag{}, nullopt_t::__secret_tag{}}; 2050b57cec5SDimitry Andric 2060b57cec5SDimitry Andrictemplate <class _Tp, bool = is_trivially_destructible<_Tp>::value> 2070b57cec5SDimitry Andricstruct __optional_destruct_base; 2080b57cec5SDimitry Andric 2090b57cec5SDimitry Andrictemplate <class _Tp> 2100b57cec5SDimitry Andricstruct __optional_destruct_base<_Tp, false> 2110b57cec5SDimitry Andric{ 2120b57cec5SDimitry Andric typedef _Tp value_type; 2130b57cec5SDimitry Andric static_assert(is_object_v<value_type>, 2140b57cec5SDimitry Andric "instantiation of optional with a non-object type is undefined behavior"); 2150b57cec5SDimitry Andric union 2160b57cec5SDimitry Andric { 2170b57cec5SDimitry Andric char __null_state_; 2180b57cec5SDimitry Andric value_type __val_; 2190b57cec5SDimitry Andric }; 2200b57cec5SDimitry Andric bool __engaged_; 2210b57cec5SDimitry Andric 2220b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY 2230b57cec5SDimitry Andric ~__optional_destruct_base() 2240b57cec5SDimitry Andric { 2250b57cec5SDimitry Andric if (__engaged_) 2260b57cec5SDimitry Andric __val_.~value_type(); 2270b57cec5SDimitry Andric } 2280b57cec5SDimitry Andric 2290b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY 2300b57cec5SDimitry Andric constexpr __optional_destruct_base() noexcept 2310b57cec5SDimitry Andric : __null_state_(), 2320b57cec5SDimitry Andric __engaged_(false) {} 2330b57cec5SDimitry Andric 2340b57cec5SDimitry Andric template <class... _Args> 2350b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY 2360b57cec5SDimitry Andric constexpr explicit __optional_destruct_base(in_place_t, _Args&&... __args) 2370b57cec5SDimitry Andric : __val_(_VSTD::forward<_Args>(__args)...), 2380b57cec5SDimitry Andric __engaged_(true) {} 2390b57cec5SDimitry Andric 2400b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY 2410b57cec5SDimitry Andric void reset() noexcept 2420b57cec5SDimitry Andric { 2430b57cec5SDimitry Andric if (__engaged_) 2440b57cec5SDimitry Andric { 2450b57cec5SDimitry Andric __val_.~value_type(); 2460b57cec5SDimitry Andric __engaged_ = false; 2470b57cec5SDimitry Andric } 2480b57cec5SDimitry Andric } 2490b57cec5SDimitry Andric}; 2500b57cec5SDimitry Andric 2510b57cec5SDimitry Andrictemplate <class _Tp> 2520b57cec5SDimitry Andricstruct __optional_destruct_base<_Tp, true> 2530b57cec5SDimitry Andric{ 2540b57cec5SDimitry Andric typedef _Tp value_type; 2550b57cec5SDimitry Andric static_assert(is_object_v<value_type>, 2560b57cec5SDimitry Andric "instantiation of optional with a non-object type is undefined behavior"); 2570b57cec5SDimitry Andric union 2580b57cec5SDimitry Andric { 2590b57cec5SDimitry Andric char __null_state_; 2600b57cec5SDimitry Andric value_type __val_; 2610b57cec5SDimitry Andric }; 2620b57cec5SDimitry Andric bool __engaged_; 2630b57cec5SDimitry Andric 2640b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY 2650b57cec5SDimitry Andric constexpr __optional_destruct_base() noexcept 2660b57cec5SDimitry Andric : __null_state_(), 2670b57cec5SDimitry Andric __engaged_(false) {} 2680b57cec5SDimitry Andric 2690b57cec5SDimitry Andric template <class... _Args> 2700b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY 2710b57cec5SDimitry Andric constexpr explicit __optional_destruct_base(in_place_t, _Args&&... __args) 2720b57cec5SDimitry Andric : __val_(_VSTD::forward<_Args>(__args)...), 2730b57cec5SDimitry Andric __engaged_(true) {} 2740b57cec5SDimitry Andric 2750b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY 2760b57cec5SDimitry Andric void reset() noexcept 2770b57cec5SDimitry Andric { 2780b57cec5SDimitry Andric if (__engaged_) 2790b57cec5SDimitry Andric { 2800b57cec5SDimitry Andric __engaged_ = false; 2810b57cec5SDimitry Andric } 2820b57cec5SDimitry Andric } 2830b57cec5SDimitry Andric}; 2840b57cec5SDimitry Andric 2850b57cec5SDimitry Andrictemplate <class _Tp, bool = is_reference<_Tp>::value> 2860b57cec5SDimitry Andricstruct __optional_storage_base : __optional_destruct_base<_Tp> 2870b57cec5SDimitry Andric{ 2880b57cec5SDimitry Andric using __base = __optional_destruct_base<_Tp>; 2890b57cec5SDimitry Andric using value_type = _Tp; 2900b57cec5SDimitry Andric using __base::__base; 2910b57cec5SDimitry Andric 2920b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY 2930b57cec5SDimitry Andric constexpr bool has_value() const noexcept 2940b57cec5SDimitry Andric { 2950b57cec5SDimitry Andric return this->__engaged_; 2960b57cec5SDimitry Andric } 2970b57cec5SDimitry Andric 2980b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY 2990b57cec5SDimitry Andric constexpr value_type& __get() & noexcept 3000b57cec5SDimitry Andric { 3010b57cec5SDimitry Andric return this->__val_; 3020b57cec5SDimitry Andric } 3030b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY 3040b57cec5SDimitry Andric constexpr const value_type& __get() const& noexcept 3050b57cec5SDimitry Andric { 3060b57cec5SDimitry Andric return this->__val_; 3070b57cec5SDimitry Andric } 3080b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY 3090b57cec5SDimitry Andric constexpr value_type&& __get() && noexcept 3100b57cec5SDimitry Andric { 3110b57cec5SDimitry Andric return _VSTD::move(this->__val_); 3120b57cec5SDimitry Andric } 3130b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY 3140b57cec5SDimitry Andric constexpr const value_type&& __get() const&& noexcept 3150b57cec5SDimitry Andric { 3160b57cec5SDimitry Andric return _VSTD::move(this->__val_); 3170b57cec5SDimitry Andric } 3180b57cec5SDimitry Andric 3190b57cec5SDimitry Andric template <class... _Args> 3200b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY 3210b57cec5SDimitry Andric void __construct(_Args&&... __args) 3220b57cec5SDimitry Andric { 3230b57cec5SDimitry Andric _LIBCPP_ASSERT(!has_value(), "__construct called for engaged __optional_storage"); 3240b57cec5SDimitry Andric ::new ((void*)_VSTD::addressof(this->__val_)) value_type(_VSTD::forward<_Args>(__args)...); 3250b57cec5SDimitry Andric this->__engaged_ = true; 3260b57cec5SDimitry Andric } 3270b57cec5SDimitry Andric 3280b57cec5SDimitry Andric template <class _That> 3290b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY 3300b57cec5SDimitry Andric void __construct_from(_That&& __opt) 3310b57cec5SDimitry Andric { 3320b57cec5SDimitry Andric if (__opt.has_value()) 3330b57cec5SDimitry Andric __construct(_VSTD::forward<_That>(__opt).__get()); 3340b57cec5SDimitry Andric } 3350b57cec5SDimitry Andric 3360b57cec5SDimitry Andric template <class _That> 3370b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY 3380b57cec5SDimitry Andric void __assign_from(_That&& __opt) 3390b57cec5SDimitry Andric { 3400b57cec5SDimitry Andric if (this->__engaged_ == __opt.has_value()) 3410b57cec5SDimitry Andric { 3420b57cec5SDimitry Andric if (this->__engaged_) 3430b57cec5SDimitry Andric this->__val_ = _VSTD::forward<_That>(__opt).__get(); 3440b57cec5SDimitry Andric } 3450b57cec5SDimitry Andric else 3460b57cec5SDimitry Andric { 3470b57cec5SDimitry Andric if (this->__engaged_) 3480b57cec5SDimitry Andric this->reset(); 3490b57cec5SDimitry Andric else 3500b57cec5SDimitry Andric __construct(_VSTD::forward<_That>(__opt).__get()); 3510b57cec5SDimitry Andric } 3520b57cec5SDimitry Andric } 3530b57cec5SDimitry Andric}; 3540b57cec5SDimitry Andric 3550b57cec5SDimitry Andric// optional<T&> is currently required ill-formed, however it may to be in the 3560b57cec5SDimitry Andric// future. For this reason it has already been implemented to ensure we can 3570b57cec5SDimitry Andric// make the change in an ABI compatible manner. 3580b57cec5SDimitry Andrictemplate <class _Tp> 3590b57cec5SDimitry Andricstruct __optional_storage_base<_Tp, true> 3600b57cec5SDimitry Andric{ 3610b57cec5SDimitry Andric using value_type = _Tp; 3620b57cec5SDimitry Andric using __raw_type = remove_reference_t<_Tp>; 3630b57cec5SDimitry Andric __raw_type* __value_; 3640b57cec5SDimitry Andric 3650b57cec5SDimitry Andric template <class _Up> 3660b57cec5SDimitry Andric static constexpr bool __can_bind_reference() { 3670b57cec5SDimitry Andric using _RawUp = typename remove_reference<_Up>::type; 3680b57cec5SDimitry Andric using _UpPtr = _RawUp*; 3690b57cec5SDimitry Andric using _RawTp = typename remove_reference<_Tp>::type; 3700b57cec5SDimitry Andric using _TpPtr = _RawTp*; 3710b57cec5SDimitry Andric using _CheckLValueArg = integral_constant<bool, 3720b57cec5SDimitry Andric (is_lvalue_reference<_Up>::value && is_convertible<_UpPtr, _TpPtr>::value) 3730b57cec5SDimitry Andric || is_same<_RawUp, reference_wrapper<_RawTp>>::value 3740b57cec5SDimitry Andric || is_same<_RawUp, reference_wrapper<typename remove_const<_RawTp>::type>>::value 3750b57cec5SDimitry Andric >; 3760b57cec5SDimitry Andric return (is_lvalue_reference<_Tp>::value && _CheckLValueArg::value) 3770b57cec5SDimitry Andric || (is_rvalue_reference<_Tp>::value && !is_lvalue_reference<_Up>::value && 3780b57cec5SDimitry Andric is_convertible<_UpPtr, _TpPtr>::value); 3790b57cec5SDimitry Andric } 3800b57cec5SDimitry Andric 3810b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY 3820b57cec5SDimitry Andric constexpr __optional_storage_base() noexcept 3830b57cec5SDimitry Andric : __value_(nullptr) {} 3840b57cec5SDimitry Andric 3850b57cec5SDimitry Andric template <class _UArg> 3860b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY 3870b57cec5SDimitry Andric constexpr explicit __optional_storage_base(in_place_t, _UArg&& __uarg) 3880b57cec5SDimitry Andric : __value_(_VSTD::addressof(__uarg)) 3890b57cec5SDimitry Andric { 3900b57cec5SDimitry Andric static_assert(__can_bind_reference<_UArg>(), 3910b57cec5SDimitry Andric "Attempted to construct a reference element in tuple from a " 3920b57cec5SDimitry Andric "possible temporary"); 3930b57cec5SDimitry Andric } 3940b57cec5SDimitry Andric 3950b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY 3960b57cec5SDimitry Andric void reset() noexcept { __value_ = nullptr; } 3970b57cec5SDimitry Andric 3980b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY 3990b57cec5SDimitry Andric constexpr bool has_value() const noexcept 4000b57cec5SDimitry Andric { return __value_ != nullptr; } 4010b57cec5SDimitry Andric 4020b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY 4030b57cec5SDimitry Andric constexpr value_type& __get() const& noexcept 4040b57cec5SDimitry Andric { return *__value_; } 4050b57cec5SDimitry Andric 4060b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY 4070b57cec5SDimitry Andric constexpr value_type&& __get() const&& noexcept 4080b57cec5SDimitry Andric { return _VSTD::forward<value_type>(*__value_); } 4090b57cec5SDimitry Andric 4100b57cec5SDimitry Andric template <class _UArg> 4110b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY 4120b57cec5SDimitry Andric void __construct(_UArg&& __val) 4130b57cec5SDimitry Andric { 4140b57cec5SDimitry Andric _LIBCPP_ASSERT(!has_value(), "__construct called for engaged __optional_storage"); 4150b57cec5SDimitry Andric static_assert(__can_bind_reference<_UArg>(), 4160b57cec5SDimitry Andric "Attempted to construct a reference element in tuple from a " 4170b57cec5SDimitry Andric "possible temporary"); 4180b57cec5SDimitry Andric __value_ = _VSTD::addressof(__val); 4190b57cec5SDimitry Andric } 4200b57cec5SDimitry Andric 4210b57cec5SDimitry Andric template <class _That> 4220b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY 4230b57cec5SDimitry Andric void __construct_from(_That&& __opt) 4240b57cec5SDimitry Andric { 4250b57cec5SDimitry Andric if (__opt.has_value()) 4260b57cec5SDimitry Andric __construct(_VSTD::forward<_That>(__opt).__get()); 4270b57cec5SDimitry Andric } 4280b57cec5SDimitry Andric 4290b57cec5SDimitry Andric template <class _That> 4300b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY 4310b57cec5SDimitry Andric void __assign_from(_That&& __opt) 4320b57cec5SDimitry Andric { 4330b57cec5SDimitry Andric if (has_value() == __opt.has_value()) 4340b57cec5SDimitry Andric { 4350b57cec5SDimitry Andric if (has_value()) 4360b57cec5SDimitry Andric *__value_ = _VSTD::forward<_That>(__opt).__get(); 4370b57cec5SDimitry Andric } 4380b57cec5SDimitry Andric else 4390b57cec5SDimitry Andric { 4400b57cec5SDimitry Andric if (has_value()) 4410b57cec5SDimitry Andric reset(); 4420b57cec5SDimitry Andric else 4430b57cec5SDimitry Andric __construct(_VSTD::forward<_That>(__opt).__get()); 4440b57cec5SDimitry Andric } 4450b57cec5SDimitry Andric } 4460b57cec5SDimitry Andric}; 4470b57cec5SDimitry Andric 4480b57cec5SDimitry Andrictemplate <class _Tp, bool = is_trivially_copy_constructible<_Tp>::value> 4490b57cec5SDimitry Andricstruct __optional_copy_base : __optional_storage_base<_Tp> 4500b57cec5SDimitry Andric{ 4510b57cec5SDimitry Andric using __optional_storage_base<_Tp>::__optional_storage_base; 4520b57cec5SDimitry Andric}; 4530b57cec5SDimitry Andric 4540b57cec5SDimitry Andrictemplate <class _Tp> 4550b57cec5SDimitry Andricstruct __optional_copy_base<_Tp, false> : __optional_storage_base<_Tp> 4560b57cec5SDimitry Andric{ 4570b57cec5SDimitry Andric using __optional_storage_base<_Tp>::__optional_storage_base; 4580b57cec5SDimitry Andric 4590b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY 4600b57cec5SDimitry Andric __optional_copy_base() = default; 4610b57cec5SDimitry Andric 4620b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY 4630b57cec5SDimitry Andric __optional_copy_base(const __optional_copy_base& __opt) 4640b57cec5SDimitry Andric { 4650b57cec5SDimitry Andric this->__construct_from(__opt); 4660b57cec5SDimitry Andric } 4670b57cec5SDimitry Andric 4680b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY 4690b57cec5SDimitry Andric __optional_copy_base(__optional_copy_base&&) = default; 4700b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY 4710b57cec5SDimitry Andric __optional_copy_base& operator=(const __optional_copy_base&) = default; 4720b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY 4730b57cec5SDimitry Andric __optional_copy_base& operator=(__optional_copy_base&&) = default; 4740b57cec5SDimitry Andric}; 4750b57cec5SDimitry Andric 4760b57cec5SDimitry Andrictemplate <class _Tp, bool = is_trivially_move_constructible<_Tp>::value> 4770b57cec5SDimitry Andricstruct __optional_move_base : __optional_copy_base<_Tp> 4780b57cec5SDimitry Andric{ 4790b57cec5SDimitry Andric using __optional_copy_base<_Tp>::__optional_copy_base; 4800b57cec5SDimitry Andric}; 4810b57cec5SDimitry Andric 4820b57cec5SDimitry Andrictemplate <class _Tp> 4830b57cec5SDimitry Andricstruct __optional_move_base<_Tp, false> : __optional_copy_base<_Tp> 4840b57cec5SDimitry Andric{ 4850b57cec5SDimitry Andric using value_type = _Tp; 4860b57cec5SDimitry Andric using __optional_copy_base<_Tp>::__optional_copy_base; 4870b57cec5SDimitry Andric 4880b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY 4890b57cec5SDimitry Andric __optional_move_base() = default; 4900b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY 4910b57cec5SDimitry Andric __optional_move_base(const __optional_move_base&) = default; 4920b57cec5SDimitry Andric 4930b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY 4940b57cec5SDimitry Andric __optional_move_base(__optional_move_base&& __opt) 4950b57cec5SDimitry Andric noexcept(is_nothrow_move_constructible_v<value_type>) 4960b57cec5SDimitry Andric { 4970b57cec5SDimitry Andric this->__construct_from(_VSTD::move(__opt)); 4980b57cec5SDimitry Andric } 4990b57cec5SDimitry Andric 5000b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY 5010b57cec5SDimitry Andric __optional_move_base& operator=(const __optional_move_base&) = default; 5020b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY 5030b57cec5SDimitry Andric __optional_move_base& operator=(__optional_move_base&&) = default; 5040b57cec5SDimitry Andric}; 5050b57cec5SDimitry Andric 5060b57cec5SDimitry Andrictemplate <class _Tp, bool = 5070b57cec5SDimitry Andric is_trivially_destructible<_Tp>::value && 5080b57cec5SDimitry Andric is_trivially_copy_constructible<_Tp>::value && 5090b57cec5SDimitry Andric is_trivially_copy_assignable<_Tp>::value> 5100b57cec5SDimitry Andricstruct __optional_copy_assign_base : __optional_move_base<_Tp> 5110b57cec5SDimitry Andric{ 5120b57cec5SDimitry Andric using __optional_move_base<_Tp>::__optional_move_base; 5130b57cec5SDimitry Andric}; 5140b57cec5SDimitry Andric 5150b57cec5SDimitry Andrictemplate <class _Tp> 5160b57cec5SDimitry Andricstruct __optional_copy_assign_base<_Tp, false> : __optional_move_base<_Tp> 5170b57cec5SDimitry Andric{ 5180b57cec5SDimitry Andric using __optional_move_base<_Tp>::__optional_move_base; 5190b57cec5SDimitry Andric 5200b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY 5210b57cec5SDimitry Andric __optional_copy_assign_base() = default; 5220b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY 5230b57cec5SDimitry Andric __optional_copy_assign_base(const __optional_copy_assign_base&) = default; 5240b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY 5250b57cec5SDimitry Andric __optional_copy_assign_base(__optional_copy_assign_base&&) = default; 5260b57cec5SDimitry Andric 5270b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY 5280b57cec5SDimitry Andric __optional_copy_assign_base& operator=(const __optional_copy_assign_base& __opt) 5290b57cec5SDimitry Andric { 5300b57cec5SDimitry Andric this->__assign_from(__opt); 5310b57cec5SDimitry Andric return *this; 5320b57cec5SDimitry Andric } 5330b57cec5SDimitry Andric 5340b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY 5350b57cec5SDimitry Andric __optional_copy_assign_base& operator=(__optional_copy_assign_base&&) = default; 5360b57cec5SDimitry Andric}; 5370b57cec5SDimitry Andric 5380b57cec5SDimitry Andrictemplate <class _Tp, bool = 5390b57cec5SDimitry Andric is_trivially_destructible<_Tp>::value && 5400b57cec5SDimitry Andric is_trivially_move_constructible<_Tp>::value && 5410b57cec5SDimitry Andric is_trivially_move_assignable<_Tp>::value> 5420b57cec5SDimitry Andricstruct __optional_move_assign_base : __optional_copy_assign_base<_Tp> 5430b57cec5SDimitry Andric{ 5440b57cec5SDimitry Andric using __optional_copy_assign_base<_Tp>::__optional_copy_assign_base; 5450b57cec5SDimitry Andric}; 5460b57cec5SDimitry Andric 5470b57cec5SDimitry Andrictemplate <class _Tp> 5480b57cec5SDimitry Andricstruct __optional_move_assign_base<_Tp, false> : __optional_copy_assign_base<_Tp> 5490b57cec5SDimitry Andric{ 5500b57cec5SDimitry Andric using value_type = _Tp; 5510b57cec5SDimitry Andric using __optional_copy_assign_base<_Tp>::__optional_copy_assign_base; 5520b57cec5SDimitry Andric 5530b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY 5540b57cec5SDimitry Andric __optional_move_assign_base() = default; 5550b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY 5560b57cec5SDimitry Andric __optional_move_assign_base(const __optional_move_assign_base& __opt) = default; 5570b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY 5580b57cec5SDimitry Andric __optional_move_assign_base(__optional_move_assign_base&&) = default; 5590b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY 5600b57cec5SDimitry Andric __optional_move_assign_base& operator=(const __optional_move_assign_base&) = default; 5610b57cec5SDimitry Andric 5620b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY 5630b57cec5SDimitry Andric __optional_move_assign_base& operator=(__optional_move_assign_base&& __opt) 5640b57cec5SDimitry Andric noexcept(is_nothrow_move_assignable_v<value_type> && 5650b57cec5SDimitry Andric is_nothrow_move_constructible_v<value_type>) 5660b57cec5SDimitry Andric { 5670b57cec5SDimitry Andric this->__assign_from(_VSTD::move(__opt)); 5680b57cec5SDimitry Andric return *this; 5690b57cec5SDimitry Andric } 5700b57cec5SDimitry Andric}; 5710b57cec5SDimitry Andric 5720b57cec5SDimitry Andrictemplate <class _Tp> 5730b57cec5SDimitry Andricusing __optional_sfinae_ctor_base_t = __sfinae_ctor_base< 5740b57cec5SDimitry Andric is_copy_constructible<_Tp>::value, 5750b57cec5SDimitry Andric is_move_constructible<_Tp>::value 5760b57cec5SDimitry Andric>; 5770b57cec5SDimitry Andric 5780b57cec5SDimitry Andrictemplate <class _Tp> 5790b57cec5SDimitry Andricusing __optional_sfinae_assign_base_t = __sfinae_assign_base< 5800b57cec5SDimitry Andric (is_copy_constructible<_Tp>::value && is_copy_assignable<_Tp>::value), 5810b57cec5SDimitry Andric (is_move_constructible<_Tp>::value && is_move_assignable<_Tp>::value) 5820b57cec5SDimitry Andric>; 5830b57cec5SDimitry Andric 5840b57cec5SDimitry Andrictemplate <class _Tp> 5850b57cec5SDimitry Andricclass optional 5860b57cec5SDimitry Andric : private __optional_move_assign_base<_Tp> 5870b57cec5SDimitry Andric , private __optional_sfinae_ctor_base_t<_Tp> 5880b57cec5SDimitry Andric , private __optional_sfinae_assign_base_t<_Tp> 5890b57cec5SDimitry Andric{ 5900b57cec5SDimitry Andric using __base = __optional_move_assign_base<_Tp>; 5910b57cec5SDimitry Andricpublic: 5920b57cec5SDimitry Andric using value_type = _Tp; 5930b57cec5SDimitry Andric 5940b57cec5SDimitry Andricprivate: 5950b57cec5SDimitry Andric // Disable the reference extension using this static assert. 5960b57cec5SDimitry Andric static_assert(!is_same_v<__uncvref_t<value_type>, in_place_t>, 5970b57cec5SDimitry Andric "instantiation of optional with in_place_t is ill-formed"); 5980b57cec5SDimitry Andric static_assert(!is_same_v<__uncvref_t<value_type>, nullopt_t>, 5990b57cec5SDimitry Andric "instantiation of optional with nullopt_t is ill-formed"); 6000b57cec5SDimitry Andric static_assert(!is_reference_v<value_type>, 6010b57cec5SDimitry Andric "instantiation of optional with a reference type is ill-formed"); 6020b57cec5SDimitry Andric static_assert(is_destructible_v<value_type>, 6030b57cec5SDimitry Andric "instantiation of optional with a non-destructible type is ill-formed"); 6040b57cec5SDimitry Andric static_assert(!is_array_v<value_type>, 6050b57cec5SDimitry Andric "instantiation of optional with an array type is ill-formed"); 6060b57cec5SDimitry Andric 6070b57cec5SDimitry Andric // LWG2756: conditionally explicit conversion from _Up 6080b57cec5SDimitry Andric struct _CheckOptionalArgsConstructor { 6090b57cec5SDimitry Andric template <class _Up> 6100b57cec5SDimitry Andric static constexpr bool __enable_implicit() { 6110b57cec5SDimitry Andric return is_constructible_v<_Tp, _Up&&> && 6120b57cec5SDimitry Andric is_convertible_v<_Up&&, _Tp>; 6130b57cec5SDimitry Andric } 6140b57cec5SDimitry Andric 6150b57cec5SDimitry Andric template <class _Up> 6160b57cec5SDimitry Andric static constexpr bool __enable_explicit() { 6170b57cec5SDimitry Andric return is_constructible_v<_Tp, _Up&&> && 6180b57cec5SDimitry Andric !is_convertible_v<_Up&&, _Tp>; 6190b57cec5SDimitry Andric } 6200b57cec5SDimitry Andric }; 6210b57cec5SDimitry Andric template <class _Up> 6220b57cec5SDimitry Andric using _CheckOptionalArgsCtor = _If< 6230b57cec5SDimitry Andric _IsNotSame<__uncvref_t<_Up>, in_place_t>::value && 6240b57cec5SDimitry Andric _IsNotSame<__uncvref_t<_Up>, optional>::value, 6250b57cec5SDimitry Andric _CheckOptionalArgsConstructor, 6260b57cec5SDimitry Andric __check_tuple_constructor_fail 6270b57cec5SDimitry Andric >; 6280b57cec5SDimitry Andric template <class _QualUp> 6290b57cec5SDimitry Andric struct _CheckOptionalLikeConstructor { 6300b57cec5SDimitry Andric template <class _Up, class _Opt = optional<_Up>> 6310b57cec5SDimitry Andric using __check_constructible_from_opt = _Or< 6320b57cec5SDimitry Andric is_constructible<_Tp, _Opt&>, 6330b57cec5SDimitry Andric is_constructible<_Tp, _Opt const&>, 6340b57cec5SDimitry Andric is_constructible<_Tp, _Opt&&>, 6350b57cec5SDimitry Andric is_constructible<_Tp, _Opt const&&>, 6360b57cec5SDimitry Andric is_convertible<_Opt&, _Tp>, 6370b57cec5SDimitry Andric is_convertible<_Opt const&, _Tp>, 6380b57cec5SDimitry Andric is_convertible<_Opt&&, _Tp>, 6390b57cec5SDimitry Andric is_convertible<_Opt const&&, _Tp> 6400b57cec5SDimitry Andric >; 6410b57cec5SDimitry Andric template <class _Up, class _Opt = optional<_Up>> 6420b57cec5SDimitry Andric using __check_assignable_from_opt = _Or< 6430b57cec5SDimitry Andric is_assignable<_Tp&, _Opt&>, 6440b57cec5SDimitry Andric is_assignable<_Tp&, _Opt const&>, 6450b57cec5SDimitry Andric is_assignable<_Tp&, _Opt&&>, 6460b57cec5SDimitry Andric is_assignable<_Tp&, _Opt const&&> 6470b57cec5SDimitry Andric >; 6480b57cec5SDimitry Andric template <class _Up, class _QUp = _QualUp> 6490b57cec5SDimitry Andric static constexpr bool __enable_implicit() { 6500b57cec5SDimitry Andric return is_convertible<_QUp, _Tp>::value && 6510b57cec5SDimitry Andric !__check_constructible_from_opt<_Up>::value; 6520b57cec5SDimitry Andric } 6530b57cec5SDimitry Andric template <class _Up, class _QUp = _QualUp> 6540b57cec5SDimitry Andric static constexpr bool __enable_explicit() { 6550b57cec5SDimitry Andric return !is_convertible<_QUp, _Tp>::value && 6560b57cec5SDimitry Andric !__check_constructible_from_opt<_Up>::value; 6570b57cec5SDimitry Andric } 6580b57cec5SDimitry Andric template <class _Up, class _QUp = _QualUp> 6590b57cec5SDimitry Andric static constexpr bool __enable_assign() { 660*e8d8bef9SDimitry Andric // Construction and assignability of _QUp to _Tp has already been 6610b57cec5SDimitry Andric // checked. 6620b57cec5SDimitry Andric return !__check_constructible_from_opt<_Up>::value && 6630b57cec5SDimitry Andric !__check_assignable_from_opt<_Up>::value; 6640b57cec5SDimitry Andric } 6650b57cec5SDimitry Andric }; 6660b57cec5SDimitry Andric 6670b57cec5SDimitry Andric template <class _Up, class _QualUp> 6680b57cec5SDimitry Andric using _CheckOptionalLikeCtor = _If< 6690b57cec5SDimitry Andric _And< 6700b57cec5SDimitry Andric _IsNotSame<_Up, _Tp>, 6710b57cec5SDimitry Andric is_constructible<_Tp, _QualUp> 6720b57cec5SDimitry Andric >::value, 6730b57cec5SDimitry Andric _CheckOptionalLikeConstructor<_QualUp>, 6740b57cec5SDimitry Andric __check_tuple_constructor_fail 6750b57cec5SDimitry Andric >; 6760b57cec5SDimitry Andric template <class _Up, class _QualUp> 6770b57cec5SDimitry Andric using _CheckOptionalLikeAssign = _If< 6780b57cec5SDimitry Andric _And< 6790b57cec5SDimitry Andric _IsNotSame<_Up, _Tp>, 6800b57cec5SDimitry Andric is_constructible<_Tp, _QualUp>, 6810b57cec5SDimitry Andric is_assignable<_Tp&, _QualUp> 6820b57cec5SDimitry Andric >::value, 6830b57cec5SDimitry Andric _CheckOptionalLikeConstructor<_QualUp>, 6840b57cec5SDimitry Andric __check_tuple_constructor_fail 6850b57cec5SDimitry Andric >; 6860b57cec5SDimitry Andricpublic: 6870b57cec5SDimitry Andric 6880b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY constexpr optional() noexcept {} 6890b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY constexpr optional(const optional&) = default; 6900b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY constexpr optional(optional&&) = default; 6910b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY constexpr optional(nullopt_t) noexcept {} 6920b57cec5SDimitry Andric 6930b57cec5SDimitry Andric template <class _InPlaceT, class... _Args, class = _EnableIf< 6940b57cec5SDimitry Andric _And< 6950b57cec5SDimitry Andric _IsSame<_InPlaceT, in_place_t>, 6960b57cec5SDimitry Andric is_constructible<value_type, _Args...> 6970b57cec5SDimitry Andric >::value 6980b57cec5SDimitry Andric > 6990b57cec5SDimitry Andric > 7000b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY 7010b57cec5SDimitry Andric constexpr explicit optional(_InPlaceT, _Args&&... __args) 7020b57cec5SDimitry Andric : __base(in_place, _VSTD::forward<_Args>(__args)...) {} 7030b57cec5SDimitry Andric 7040b57cec5SDimitry Andric template <class _Up, class... _Args, class = _EnableIf< 7050b57cec5SDimitry Andric is_constructible_v<value_type, initializer_list<_Up>&, _Args...>> 7060b57cec5SDimitry Andric > 7070b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY 7080b57cec5SDimitry Andric constexpr explicit optional(in_place_t, initializer_list<_Up> __il, _Args&&... __args) 7090b57cec5SDimitry Andric : __base(in_place, __il, _VSTD::forward<_Args>(__args)...) {} 7100b57cec5SDimitry Andric 7110b57cec5SDimitry Andric template <class _Up = value_type, _EnableIf< 7120b57cec5SDimitry Andric _CheckOptionalArgsCtor<_Up>::template __enable_implicit<_Up>() 7130b57cec5SDimitry Andric , int> = 0> 7140b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY 7150b57cec5SDimitry Andric constexpr optional(_Up&& __v) 7160b57cec5SDimitry Andric : __base(in_place, _VSTD::forward<_Up>(__v)) {} 7170b57cec5SDimitry Andric 7180b57cec5SDimitry Andric template <class _Up, _EnableIf< 7190b57cec5SDimitry Andric _CheckOptionalArgsCtor<_Up>::template __enable_explicit<_Up>() 7200b57cec5SDimitry Andric , int> = 0> 7210b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY 7220b57cec5SDimitry Andric constexpr explicit optional(_Up&& __v) 7230b57cec5SDimitry Andric : __base(in_place, _VSTD::forward<_Up>(__v)) {} 7240b57cec5SDimitry Andric 7250b57cec5SDimitry Andric // LWG2756: conditionally explicit conversion from const optional<_Up>& 7260b57cec5SDimitry Andric template <class _Up, _EnableIf< 7270b57cec5SDimitry Andric _CheckOptionalLikeCtor<_Up, _Up const&>::template __enable_implicit<_Up>() 7280b57cec5SDimitry Andric , int> = 0> 7290b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY 7300b57cec5SDimitry Andric optional(const optional<_Up>& __v) 7310b57cec5SDimitry Andric { 7320b57cec5SDimitry Andric this->__construct_from(__v); 7330b57cec5SDimitry Andric } 7340b57cec5SDimitry Andric template <class _Up, _EnableIf< 7350b57cec5SDimitry Andric _CheckOptionalLikeCtor<_Up, _Up const&>::template __enable_explicit<_Up>() 7360b57cec5SDimitry Andric , int> = 0> 7370b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY 7380b57cec5SDimitry Andric explicit optional(const optional<_Up>& __v) 7390b57cec5SDimitry Andric { 7400b57cec5SDimitry Andric this->__construct_from(__v); 7410b57cec5SDimitry Andric } 7420b57cec5SDimitry Andric 7430b57cec5SDimitry Andric // LWG2756: conditionally explicit conversion from optional<_Up>&& 7440b57cec5SDimitry Andric template <class _Up, _EnableIf< 7450b57cec5SDimitry Andric _CheckOptionalLikeCtor<_Up, _Up &&>::template __enable_implicit<_Up>() 7460b57cec5SDimitry Andric , int> = 0> 7470b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY 7480b57cec5SDimitry Andric optional(optional<_Up>&& __v) 7490b57cec5SDimitry Andric { 7500b57cec5SDimitry Andric this->__construct_from(_VSTD::move(__v)); 7510b57cec5SDimitry Andric } 7520b57cec5SDimitry Andric template <class _Up, _EnableIf< 7530b57cec5SDimitry Andric _CheckOptionalLikeCtor<_Up, _Up &&>::template __enable_explicit<_Up>() 7540b57cec5SDimitry Andric , int> = 0> 7550b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY 7560b57cec5SDimitry Andric explicit optional(optional<_Up>&& __v) 7570b57cec5SDimitry Andric { 7580b57cec5SDimitry Andric this->__construct_from(_VSTD::move(__v)); 7590b57cec5SDimitry Andric } 7600b57cec5SDimitry Andric 7610b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY 7620b57cec5SDimitry Andric optional& operator=(nullopt_t) noexcept 7630b57cec5SDimitry Andric { 7640b57cec5SDimitry Andric reset(); 7650b57cec5SDimitry Andric return *this; 7660b57cec5SDimitry Andric } 7670b57cec5SDimitry Andric 7680b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY optional& operator=(const optional&) = default; 7690b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY optional& operator=(optional&&) = default; 7700b57cec5SDimitry Andric 7710b57cec5SDimitry Andric // LWG2756 7720b57cec5SDimitry Andric template <class _Up = value_type, 7730b57cec5SDimitry Andric class = _EnableIf< 7740b57cec5SDimitry Andric _And< 7750b57cec5SDimitry Andric _IsNotSame<__uncvref_t<_Up>, optional>, 7760b57cec5SDimitry Andric _Or< 7770b57cec5SDimitry Andric _IsNotSame<__uncvref_t<_Up>, value_type>, 7780b57cec5SDimitry Andric _Not<is_scalar<value_type>> 7790b57cec5SDimitry Andric >, 7800b57cec5SDimitry Andric is_constructible<value_type, _Up>, 7810b57cec5SDimitry Andric is_assignable<value_type&, _Up> 7820b57cec5SDimitry Andric >::value> 7830b57cec5SDimitry Andric > 7840b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY 7850b57cec5SDimitry Andric optional& 7860b57cec5SDimitry Andric operator=(_Up&& __v) 7870b57cec5SDimitry Andric { 7880b57cec5SDimitry Andric if (this->has_value()) 7890b57cec5SDimitry Andric this->__get() = _VSTD::forward<_Up>(__v); 7900b57cec5SDimitry Andric else 7910b57cec5SDimitry Andric this->__construct(_VSTD::forward<_Up>(__v)); 7920b57cec5SDimitry Andric return *this; 7930b57cec5SDimitry Andric } 7940b57cec5SDimitry Andric 7950b57cec5SDimitry Andric // LWG2756 7960b57cec5SDimitry Andric template <class _Up, _EnableIf< 7970b57cec5SDimitry Andric _CheckOptionalLikeAssign<_Up, _Up const&>::template __enable_assign<_Up>() 7980b57cec5SDimitry Andric , int> = 0> 7990b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY 8000b57cec5SDimitry Andric optional& 8010b57cec5SDimitry Andric operator=(const optional<_Up>& __v) 8020b57cec5SDimitry Andric { 8030b57cec5SDimitry Andric this->__assign_from(__v); 8040b57cec5SDimitry Andric return *this; 8050b57cec5SDimitry Andric } 8060b57cec5SDimitry Andric 8070b57cec5SDimitry Andric // LWG2756 8080b57cec5SDimitry Andric template <class _Up, _EnableIf< 8090b57cec5SDimitry Andric _CheckOptionalLikeCtor<_Up, _Up &&>::template __enable_assign<_Up>() 8100b57cec5SDimitry Andric , int> = 0> 8110b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY 8120b57cec5SDimitry Andric optional& 8130b57cec5SDimitry Andric operator=(optional<_Up>&& __v) 8140b57cec5SDimitry Andric { 8150b57cec5SDimitry Andric this->__assign_from(_VSTD::move(__v)); 8160b57cec5SDimitry Andric return *this; 8170b57cec5SDimitry Andric } 8180b57cec5SDimitry Andric 8190b57cec5SDimitry Andric template <class... _Args, 8200b57cec5SDimitry Andric class = _EnableIf 8210b57cec5SDimitry Andric < 8220b57cec5SDimitry Andric is_constructible_v<value_type, _Args...> 8230b57cec5SDimitry Andric > 8240b57cec5SDimitry Andric > 8250b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY 8260b57cec5SDimitry Andric _Tp & 8270b57cec5SDimitry Andric emplace(_Args&&... __args) 8280b57cec5SDimitry Andric { 8290b57cec5SDimitry Andric reset(); 8300b57cec5SDimitry Andric this->__construct(_VSTD::forward<_Args>(__args)...); 8310b57cec5SDimitry Andric return this->__get(); 8320b57cec5SDimitry Andric } 8330b57cec5SDimitry Andric 8340b57cec5SDimitry Andric template <class _Up, class... _Args, 8350b57cec5SDimitry Andric class = _EnableIf 8360b57cec5SDimitry Andric < 8370b57cec5SDimitry Andric is_constructible_v<value_type, initializer_list<_Up>&, _Args...> 8380b57cec5SDimitry Andric > 8390b57cec5SDimitry Andric > 8400b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY 8410b57cec5SDimitry Andric _Tp & 8420b57cec5SDimitry Andric emplace(initializer_list<_Up> __il, _Args&&... __args) 8430b57cec5SDimitry Andric { 8440b57cec5SDimitry Andric reset(); 8450b57cec5SDimitry Andric this->__construct(__il, _VSTD::forward<_Args>(__args)...); 8460b57cec5SDimitry Andric return this->__get(); 8470b57cec5SDimitry Andric } 8480b57cec5SDimitry Andric 8490b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY 8500b57cec5SDimitry Andric void swap(optional& __opt) 8510b57cec5SDimitry Andric noexcept(is_nothrow_move_constructible_v<value_type> && 8520b57cec5SDimitry Andric is_nothrow_swappable_v<value_type>) 8530b57cec5SDimitry Andric { 8540b57cec5SDimitry Andric if (this->has_value() == __opt.has_value()) 8550b57cec5SDimitry Andric { 8560b57cec5SDimitry Andric using _VSTD::swap; 8570b57cec5SDimitry Andric if (this->has_value()) 8580b57cec5SDimitry Andric swap(this->__get(), __opt.__get()); 8590b57cec5SDimitry Andric } 8600b57cec5SDimitry Andric else 8610b57cec5SDimitry Andric { 8620b57cec5SDimitry Andric if (this->has_value()) 8630b57cec5SDimitry Andric { 8640b57cec5SDimitry Andric __opt.__construct(_VSTD::move(this->__get())); 8650b57cec5SDimitry Andric reset(); 8660b57cec5SDimitry Andric } 8670b57cec5SDimitry Andric else 8680b57cec5SDimitry Andric { 8690b57cec5SDimitry Andric this->__construct(_VSTD::move(__opt.__get())); 8700b57cec5SDimitry Andric __opt.reset(); 8710b57cec5SDimitry Andric } 8720b57cec5SDimitry Andric } 8730b57cec5SDimitry Andric } 8740b57cec5SDimitry Andric 8750b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY 8760b57cec5SDimitry Andric constexpr 8770b57cec5SDimitry Andric add_pointer_t<value_type const> 8780b57cec5SDimitry Andric operator->() const 8790b57cec5SDimitry Andric { 8800b57cec5SDimitry Andric _LIBCPP_ASSERT(this->has_value(), "optional operator-> called for disengaged value"); 8810b57cec5SDimitry Andric#ifndef _LIBCPP_HAS_NO_BUILTIN_ADDRESSOF 8820b57cec5SDimitry Andric return _VSTD::addressof(this->__get()); 8830b57cec5SDimitry Andric#else 8840b57cec5SDimitry Andric return __operator_arrow(__has_operator_addressof<value_type>{}, this->__get()); 8850b57cec5SDimitry Andric#endif 8860b57cec5SDimitry Andric } 8870b57cec5SDimitry Andric 8880b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY 8890b57cec5SDimitry Andric constexpr 8900b57cec5SDimitry Andric add_pointer_t<value_type> 8910b57cec5SDimitry Andric operator->() 8920b57cec5SDimitry Andric { 8930b57cec5SDimitry Andric _LIBCPP_ASSERT(this->has_value(), "optional operator-> called for disengaged value"); 8940b57cec5SDimitry Andric#ifndef _LIBCPP_HAS_NO_BUILTIN_ADDRESSOF 8950b57cec5SDimitry Andric return _VSTD::addressof(this->__get()); 8960b57cec5SDimitry Andric#else 8970b57cec5SDimitry Andric return __operator_arrow(__has_operator_addressof<value_type>{}, this->__get()); 8980b57cec5SDimitry Andric#endif 8990b57cec5SDimitry Andric } 9000b57cec5SDimitry Andric 9010b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY 9020b57cec5SDimitry Andric constexpr 9030b57cec5SDimitry Andric const value_type& 9040b57cec5SDimitry Andric operator*() const& 9050b57cec5SDimitry Andric { 9060b57cec5SDimitry Andric _LIBCPP_ASSERT(this->has_value(), "optional operator* called for disengaged value"); 9070b57cec5SDimitry Andric return this->__get(); 9080b57cec5SDimitry Andric } 9090b57cec5SDimitry Andric 9100b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY 9110b57cec5SDimitry Andric constexpr 9120b57cec5SDimitry Andric value_type& 9130b57cec5SDimitry Andric operator*() & 9140b57cec5SDimitry Andric { 9150b57cec5SDimitry Andric _LIBCPP_ASSERT(this->has_value(), "optional operator* called for disengaged value"); 9160b57cec5SDimitry Andric return this->__get(); 9170b57cec5SDimitry Andric } 9180b57cec5SDimitry Andric 9190b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY 9200b57cec5SDimitry Andric constexpr 9210b57cec5SDimitry Andric value_type&& 9220b57cec5SDimitry Andric operator*() && 9230b57cec5SDimitry Andric { 9240b57cec5SDimitry Andric _LIBCPP_ASSERT(this->has_value(), "optional operator* called for disengaged value"); 9250b57cec5SDimitry Andric return _VSTD::move(this->__get()); 9260b57cec5SDimitry Andric } 9270b57cec5SDimitry Andric 9280b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY 9290b57cec5SDimitry Andric constexpr 9300b57cec5SDimitry Andric const value_type&& 9310b57cec5SDimitry Andric operator*() const&& 9320b57cec5SDimitry Andric { 9330b57cec5SDimitry Andric _LIBCPP_ASSERT(this->has_value(), "optional operator* called for disengaged value"); 9340b57cec5SDimitry Andric return _VSTD::move(this->__get()); 9350b57cec5SDimitry Andric } 9360b57cec5SDimitry Andric 9370b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY 9380b57cec5SDimitry Andric constexpr explicit operator bool() const noexcept { return has_value(); } 9390b57cec5SDimitry Andric 9400b57cec5SDimitry Andric using __base::has_value; 9410b57cec5SDimitry Andric using __base::__get; 9420b57cec5SDimitry Andric 9430b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY 9440b57cec5SDimitry Andric _LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS 9450b57cec5SDimitry Andric constexpr value_type const& value() const& 9460b57cec5SDimitry Andric { 9470b57cec5SDimitry Andric if (!this->has_value()) 9480b57cec5SDimitry Andric __throw_bad_optional_access(); 9490b57cec5SDimitry Andric return this->__get(); 9500b57cec5SDimitry Andric } 9510b57cec5SDimitry Andric 9520b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY 9530b57cec5SDimitry Andric _LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS 9540b57cec5SDimitry Andric constexpr value_type& value() & 9550b57cec5SDimitry Andric { 9560b57cec5SDimitry Andric if (!this->has_value()) 9570b57cec5SDimitry Andric __throw_bad_optional_access(); 9580b57cec5SDimitry Andric return this->__get(); 9590b57cec5SDimitry Andric } 9600b57cec5SDimitry Andric 9610b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY 9620b57cec5SDimitry Andric _LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS 9630b57cec5SDimitry Andric constexpr value_type&& value() && 9640b57cec5SDimitry Andric { 9650b57cec5SDimitry Andric if (!this->has_value()) 9660b57cec5SDimitry Andric __throw_bad_optional_access(); 9670b57cec5SDimitry Andric return _VSTD::move(this->__get()); 9680b57cec5SDimitry Andric } 9690b57cec5SDimitry Andric 9700b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY 9710b57cec5SDimitry Andric _LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS 9720b57cec5SDimitry Andric constexpr value_type const&& value() const&& 9730b57cec5SDimitry Andric { 9740b57cec5SDimitry Andric if (!this->has_value()) 9750b57cec5SDimitry Andric __throw_bad_optional_access(); 9760b57cec5SDimitry Andric return _VSTD::move(this->__get()); 9770b57cec5SDimitry Andric } 9780b57cec5SDimitry Andric 9790b57cec5SDimitry Andric template <class _Up> 9800b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY 9810b57cec5SDimitry Andric constexpr value_type value_or(_Up&& __v) const& 9820b57cec5SDimitry Andric { 9830b57cec5SDimitry Andric static_assert(is_copy_constructible_v<value_type>, 9840b57cec5SDimitry Andric "optional<T>::value_or: T must be copy constructible"); 9850b57cec5SDimitry Andric static_assert(is_convertible_v<_Up, value_type>, 9860b57cec5SDimitry Andric "optional<T>::value_or: U must be convertible to T"); 9870b57cec5SDimitry Andric return this->has_value() ? this->__get() : 9880b57cec5SDimitry Andric static_cast<value_type>(_VSTD::forward<_Up>(__v)); 9890b57cec5SDimitry Andric } 9900b57cec5SDimitry Andric 9910b57cec5SDimitry Andric template <class _Up> 9920b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY 9930b57cec5SDimitry Andric constexpr value_type value_or(_Up&& __v) && 9940b57cec5SDimitry Andric { 9950b57cec5SDimitry Andric static_assert(is_move_constructible_v<value_type>, 9960b57cec5SDimitry Andric "optional<T>::value_or: T must be move constructible"); 9970b57cec5SDimitry Andric static_assert(is_convertible_v<_Up, value_type>, 9980b57cec5SDimitry Andric "optional<T>::value_or: U must be convertible to T"); 9990b57cec5SDimitry Andric return this->has_value() ? _VSTD::move(this->__get()) : 10000b57cec5SDimitry Andric static_cast<value_type>(_VSTD::forward<_Up>(__v)); 10010b57cec5SDimitry Andric } 10020b57cec5SDimitry Andric 10030b57cec5SDimitry Andric using __base::reset; 10040b57cec5SDimitry Andric 10050b57cec5SDimitry Andricprivate: 10060b57cec5SDimitry Andric template <class _Up> 10070b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY 10080b57cec5SDimitry Andric static _Up* 10090b57cec5SDimitry Andric __operator_arrow(true_type, _Up& __x) 10100b57cec5SDimitry Andric { 10110b57cec5SDimitry Andric return _VSTD::addressof(__x); 10120b57cec5SDimitry Andric } 10130b57cec5SDimitry Andric 10140b57cec5SDimitry Andric template <class _Up> 10150b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY 10160b57cec5SDimitry Andric static constexpr _Up* 10170b57cec5SDimitry Andric __operator_arrow(false_type, _Up& __x) 10180b57cec5SDimitry Andric { 10190b57cec5SDimitry Andric return &__x; 10200b57cec5SDimitry Andric } 10210b57cec5SDimitry Andric}; 10220b57cec5SDimitry Andric 10230b57cec5SDimitry Andric#ifndef _LIBCPP_HAS_NO_DEDUCTION_GUIDES 10240b57cec5SDimitry Andrictemplate<class T> 10250b57cec5SDimitry Andric optional(T) -> optional<T>; 10260b57cec5SDimitry Andric#endif 10270b57cec5SDimitry Andric 10280b57cec5SDimitry Andric// Comparisons between optionals 10290b57cec5SDimitry Andrictemplate <class _Tp, class _Up> 10300b57cec5SDimitry Andric_LIBCPP_INLINE_VISIBILITY constexpr 10310b57cec5SDimitry Andric_EnableIf< 10320b57cec5SDimitry Andric is_convertible_v<decltype(_VSTD::declval<const _Tp&>() == 10330b57cec5SDimitry Andric _VSTD::declval<const _Up&>()), bool>, 10340b57cec5SDimitry Andric bool 10350b57cec5SDimitry Andric> 10360b57cec5SDimitry Andricoperator==(const optional<_Tp>& __x, const optional<_Up>& __y) 10370b57cec5SDimitry Andric{ 10380b57cec5SDimitry Andric if (static_cast<bool>(__x) != static_cast<bool>(__y)) 10390b57cec5SDimitry Andric return false; 10400b57cec5SDimitry Andric if (!static_cast<bool>(__x)) 10410b57cec5SDimitry Andric return true; 10420b57cec5SDimitry Andric return *__x == *__y; 10430b57cec5SDimitry Andric} 10440b57cec5SDimitry Andric 10450b57cec5SDimitry Andrictemplate <class _Tp, class _Up> 10460b57cec5SDimitry Andric_LIBCPP_INLINE_VISIBILITY constexpr 10470b57cec5SDimitry Andric_EnableIf< 10480b57cec5SDimitry Andric is_convertible_v<decltype(_VSTD::declval<const _Tp&>() != 10490b57cec5SDimitry Andric _VSTD::declval<const _Up&>()), bool>, 10500b57cec5SDimitry Andric bool 10510b57cec5SDimitry Andric> 10520b57cec5SDimitry Andricoperator!=(const optional<_Tp>& __x, const optional<_Up>& __y) 10530b57cec5SDimitry Andric{ 10540b57cec5SDimitry Andric if (static_cast<bool>(__x) != static_cast<bool>(__y)) 10550b57cec5SDimitry Andric return true; 10560b57cec5SDimitry Andric if (!static_cast<bool>(__x)) 10570b57cec5SDimitry Andric return false; 10580b57cec5SDimitry Andric return *__x != *__y; 10590b57cec5SDimitry Andric} 10600b57cec5SDimitry Andric 10610b57cec5SDimitry Andrictemplate <class _Tp, class _Up> 10620b57cec5SDimitry Andric_LIBCPP_INLINE_VISIBILITY constexpr 10630b57cec5SDimitry Andric_EnableIf< 10640b57cec5SDimitry Andric is_convertible_v<decltype(_VSTD::declval<const _Tp&>() < 10650b57cec5SDimitry Andric _VSTD::declval<const _Up&>()), bool>, 10660b57cec5SDimitry Andric bool 10670b57cec5SDimitry Andric> 10680b57cec5SDimitry Andricoperator<(const optional<_Tp>& __x, const optional<_Up>& __y) 10690b57cec5SDimitry Andric{ 10700b57cec5SDimitry Andric if (!static_cast<bool>(__y)) 10710b57cec5SDimitry Andric return false; 10720b57cec5SDimitry Andric if (!static_cast<bool>(__x)) 10730b57cec5SDimitry Andric return true; 10740b57cec5SDimitry Andric return *__x < *__y; 10750b57cec5SDimitry Andric} 10760b57cec5SDimitry Andric 10770b57cec5SDimitry Andrictemplate <class _Tp, class _Up> 10780b57cec5SDimitry Andric_LIBCPP_INLINE_VISIBILITY constexpr 10790b57cec5SDimitry Andric_EnableIf< 10800b57cec5SDimitry Andric is_convertible_v<decltype(_VSTD::declval<const _Tp&>() > 10810b57cec5SDimitry Andric _VSTD::declval<const _Up&>()), bool>, 10820b57cec5SDimitry Andric bool 10830b57cec5SDimitry Andric> 10840b57cec5SDimitry Andricoperator>(const optional<_Tp>& __x, const optional<_Up>& __y) 10850b57cec5SDimitry Andric{ 10860b57cec5SDimitry Andric if (!static_cast<bool>(__x)) 10870b57cec5SDimitry Andric return false; 10880b57cec5SDimitry Andric if (!static_cast<bool>(__y)) 10890b57cec5SDimitry Andric return true; 10900b57cec5SDimitry Andric return *__x > *__y; 10910b57cec5SDimitry Andric} 10920b57cec5SDimitry Andric 10930b57cec5SDimitry Andrictemplate <class _Tp, class _Up> 10940b57cec5SDimitry Andric_LIBCPP_INLINE_VISIBILITY constexpr 10950b57cec5SDimitry Andric_EnableIf< 10960b57cec5SDimitry Andric is_convertible_v<decltype(_VSTD::declval<const _Tp&>() <= 10970b57cec5SDimitry Andric _VSTD::declval<const _Up&>()), bool>, 10980b57cec5SDimitry Andric bool 10990b57cec5SDimitry Andric> 11000b57cec5SDimitry Andricoperator<=(const optional<_Tp>& __x, const optional<_Up>& __y) 11010b57cec5SDimitry Andric{ 11020b57cec5SDimitry Andric if (!static_cast<bool>(__x)) 11030b57cec5SDimitry Andric return true; 11040b57cec5SDimitry Andric if (!static_cast<bool>(__y)) 11050b57cec5SDimitry Andric return false; 11060b57cec5SDimitry Andric return *__x <= *__y; 11070b57cec5SDimitry Andric} 11080b57cec5SDimitry Andric 11090b57cec5SDimitry Andrictemplate <class _Tp, class _Up> 11100b57cec5SDimitry Andric_LIBCPP_INLINE_VISIBILITY constexpr 11110b57cec5SDimitry Andric_EnableIf< 11120b57cec5SDimitry Andric is_convertible_v<decltype(_VSTD::declval<const _Tp&>() >= 11130b57cec5SDimitry Andric _VSTD::declval<const _Up&>()), bool>, 11140b57cec5SDimitry Andric bool 11150b57cec5SDimitry Andric> 11160b57cec5SDimitry Andricoperator>=(const optional<_Tp>& __x, const optional<_Up>& __y) 11170b57cec5SDimitry Andric{ 11180b57cec5SDimitry Andric if (!static_cast<bool>(__y)) 11190b57cec5SDimitry Andric return true; 11200b57cec5SDimitry Andric if (!static_cast<bool>(__x)) 11210b57cec5SDimitry Andric return false; 11220b57cec5SDimitry Andric return *__x >= *__y; 11230b57cec5SDimitry Andric} 11240b57cec5SDimitry Andric 11250b57cec5SDimitry Andric// Comparisons with nullopt 11260b57cec5SDimitry Andrictemplate <class _Tp> 11270b57cec5SDimitry Andric_LIBCPP_INLINE_VISIBILITY constexpr 11280b57cec5SDimitry Andricbool 11290b57cec5SDimitry Andricoperator==(const optional<_Tp>& __x, nullopt_t) noexcept 11300b57cec5SDimitry Andric{ 11310b57cec5SDimitry Andric return !static_cast<bool>(__x); 11320b57cec5SDimitry Andric} 11330b57cec5SDimitry Andric 11340b57cec5SDimitry Andrictemplate <class _Tp> 11350b57cec5SDimitry Andric_LIBCPP_INLINE_VISIBILITY constexpr 11360b57cec5SDimitry Andricbool 11370b57cec5SDimitry Andricoperator==(nullopt_t, const optional<_Tp>& __x) noexcept 11380b57cec5SDimitry Andric{ 11390b57cec5SDimitry Andric return !static_cast<bool>(__x); 11400b57cec5SDimitry Andric} 11410b57cec5SDimitry Andric 11420b57cec5SDimitry Andrictemplate <class _Tp> 11430b57cec5SDimitry Andric_LIBCPP_INLINE_VISIBILITY constexpr 11440b57cec5SDimitry Andricbool 11450b57cec5SDimitry Andricoperator!=(const optional<_Tp>& __x, nullopt_t) noexcept 11460b57cec5SDimitry Andric{ 11470b57cec5SDimitry Andric return static_cast<bool>(__x); 11480b57cec5SDimitry Andric} 11490b57cec5SDimitry Andric 11500b57cec5SDimitry Andrictemplate <class _Tp> 11510b57cec5SDimitry Andric_LIBCPP_INLINE_VISIBILITY constexpr 11520b57cec5SDimitry Andricbool 11530b57cec5SDimitry Andricoperator!=(nullopt_t, const optional<_Tp>& __x) noexcept 11540b57cec5SDimitry Andric{ 11550b57cec5SDimitry Andric return static_cast<bool>(__x); 11560b57cec5SDimitry Andric} 11570b57cec5SDimitry Andric 11580b57cec5SDimitry Andrictemplate <class _Tp> 11590b57cec5SDimitry Andric_LIBCPP_INLINE_VISIBILITY constexpr 11600b57cec5SDimitry Andricbool 11610b57cec5SDimitry Andricoperator<(const optional<_Tp>&, nullopt_t) noexcept 11620b57cec5SDimitry Andric{ 11630b57cec5SDimitry Andric return false; 11640b57cec5SDimitry Andric} 11650b57cec5SDimitry Andric 11660b57cec5SDimitry Andrictemplate <class _Tp> 11670b57cec5SDimitry Andric_LIBCPP_INLINE_VISIBILITY constexpr 11680b57cec5SDimitry Andricbool 11690b57cec5SDimitry Andricoperator<(nullopt_t, const optional<_Tp>& __x) noexcept 11700b57cec5SDimitry Andric{ 11710b57cec5SDimitry Andric return static_cast<bool>(__x); 11720b57cec5SDimitry Andric} 11730b57cec5SDimitry Andric 11740b57cec5SDimitry Andrictemplate <class _Tp> 11750b57cec5SDimitry Andric_LIBCPP_INLINE_VISIBILITY constexpr 11760b57cec5SDimitry Andricbool 11770b57cec5SDimitry Andricoperator<=(const optional<_Tp>& __x, nullopt_t) noexcept 11780b57cec5SDimitry Andric{ 11790b57cec5SDimitry Andric return !static_cast<bool>(__x); 11800b57cec5SDimitry Andric} 11810b57cec5SDimitry Andric 11820b57cec5SDimitry Andrictemplate <class _Tp> 11830b57cec5SDimitry Andric_LIBCPP_INLINE_VISIBILITY constexpr 11840b57cec5SDimitry Andricbool 11850b57cec5SDimitry Andricoperator<=(nullopt_t, const optional<_Tp>&) noexcept 11860b57cec5SDimitry Andric{ 11870b57cec5SDimitry Andric return true; 11880b57cec5SDimitry Andric} 11890b57cec5SDimitry Andric 11900b57cec5SDimitry Andrictemplate <class _Tp> 11910b57cec5SDimitry Andric_LIBCPP_INLINE_VISIBILITY constexpr 11920b57cec5SDimitry Andricbool 11930b57cec5SDimitry Andricoperator>(const optional<_Tp>& __x, nullopt_t) noexcept 11940b57cec5SDimitry Andric{ 11950b57cec5SDimitry Andric return static_cast<bool>(__x); 11960b57cec5SDimitry Andric} 11970b57cec5SDimitry Andric 11980b57cec5SDimitry Andrictemplate <class _Tp> 11990b57cec5SDimitry Andric_LIBCPP_INLINE_VISIBILITY constexpr 12000b57cec5SDimitry Andricbool 12010b57cec5SDimitry Andricoperator>(nullopt_t, const optional<_Tp>&) noexcept 12020b57cec5SDimitry Andric{ 12030b57cec5SDimitry Andric return false; 12040b57cec5SDimitry Andric} 12050b57cec5SDimitry Andric 12060b57cec5SDimitry Andrictemplate <class _Tp> 12070b57cec5SDimitry Andric_LIBCPP_INLINE_VISIBILITY constexpr 12080b57cec5SDimitry Andricbool 12090b57cec5SDimitry Andricoperator>=(const optional<_Tp>&, nullopt_t) noexcept 12100b57cec5SDimitry Andric{ 12110b57cec5SDimitry Andric return true; 12120b57cec5SDimitry Andric} 12130b57cec5SDimitry Andric 12140b57cec5SDimitry Andrictemplate <class _Tp> 12150b57cec5SDimitry Andric_LIBCPP_INLINE_VISIBILITY constexpr 12160b57cec5SDimitry Andricbool 12170b57cec5SDimitry Andricoperator>=(nullopt_t, const optional<_Tp>& __x) noexcept 12180b57cec5SDimitry Andric{ 12190b57cec5SDimitry Andric return !static_cast<bool>(__x); 12200b57cec5SDimitry Andric} 12210b57cec5SDimitry Andric 12220b57cec5SDimitry Andric// Comparisons with T 12230b57cec5SDimitry Andrictemplate <class _Tp, class _Up> 12240b57cec5SDimitry Andric_LIBCPP_INLINE_VISIBILITY constexpr 12250b57cec5SDimitry Andric_EnableIf< 12260b57cec5SDimitry Andric is_convertible_v<decltype(_VSTD::declval<const _Tp&>() == 12270b57cec5SDimitry Andric _VSTD::declval<const _Up&>()), bool>, 12280b57cec5SDimitry Andric bool 12290b57cec5SDimitry Andric> 12300b57cec5SDimitry Andricoperator==(const optional<_Tp>& __x, const _Up& __v) 12310b57cec5SDimitry Andric{ 12320b57cec5SDimitry Andric return static_cast<bool>(__x) ? *__x == __v : false; 12330b57cec5SDimitry Andric} 12340b57cec5SDimitry Andric 12350b57cec5SDimitry Andrictemplate <class _Tp, class _Up> 12360b57cec5SDimitry Andric_LIBCPP_INLINE_VISIBILITY constexpr 12370b57cec5SDimitry Andric_EnableIf< 12380b57cec5SDimitry Andric is_convertible_v<decltype(_VSTD::declval<const _Tp&>() == 12390b57cec5SDimitry Andric _VSTD::declval<const _Up&>()), bool>, 12400b57cec5SDimitry Andric bool 12410b57cec5SDimitry Andric> 12420b57cec5SDimitry Andricoperator==(const _Tp& __v, const optional<_Up>& __x) 12430b57cec5SDimitry Andric{ 12440b57cec5SDimitry Andric return static_cast<bool>(__x) ? __v == *__x : false; 12450b57cec5SDimitry Andric} 12460b57cec5SDimitry Andric 12470b57cec5SDimitry Andrictemplate <class _Tp, class _Up> 12480b57cec5SDimitry Andric_LIBCPP_INLINE_VISIBILITY constexpr 12490b57cec5SDimitry Andric_EnableIf< 12500b57cec5SDimitry Andric is_convertible_v<decltype(_VSTD::declval<const _Tp&>() != 12510b57cec5SDimitry Andric _VSTD::declval<const _Up&>()), bool>, 12520b57cec5SDimitry Andric bool 12530b57cec5SDimitry Andric> 12540b57cec5SDimitry Andricoperator!=(const optional<_Tp>& __x, const _Up& __v) 12550b57cec5SDimitry Andric{ 12560b57cec5SDimitry Andric return static_cast<bool>(__x) ? *__x != __v : true; 12570b57cec5SDimitry Andric} 12580b57cec5SDimitry Andric 12590b57cec5SDimitry Andrictemplate <class _Tp, class _Up> 12600b57cec5SDimitry Andric_LIBCPP_INLINE_VISIBILITY constexpr 12610b57cec5SDimitry Andric_EnableIf< 12620b57cec5SDimitry Andric is_convertible_v<decltype(_VSTD::declval<const _Tp&>() != 12630b57cec5SDimitry Andric _VSTD::declval<const _Up&>()), bool>, 12640b57cec5SDimitry Andric bool 12650b57cec5SDimitry Andric> 12660b57cec5SDimitry Andricoperator!=(const _Tp& __v, const optional<_Up>& __x) 12670b57cec5SDimitry Andric{ 12680b57cec5SDimitry Andric return static_cast<bool>(__x) ? __v != *__x : true; 12690b57cec5SDimitry Andric} 12700b57cec5SDimitry Andric 12710b57cec5SDimitry Andrictemplate <class _Tp, class _Up> 12720b57cec5SDimitry Andric_LIBCPP_INLINE_VISIBILITY constexpr 12730b57cec5SDimitry Andric_EnableIf< 12740b57cec5SDimitry Andric is_convertible_v<decltype(_VSTD::declval<const _Tp&>() < 12750b57cec5SDimitry Andric _VSTD::declval<const _Up&>()), bool>, 12760b57cec5SDimitry Andric bool 12770b57cec5SDimitry Andric> 12780b57cec5SDimitry Andricoperator<(const optional<_Tp>& __x, const _Up& __v) 12790b57cec5SDimitry Andric{ 12800b57cec5SDimitry Andric return static_cast<bool>(__x) ? *__x < __v : true; 12810b57cec5SDimitry Andric} 12820b57cec5SDimitry Andric 12830b57cec5SDimitry Andrictemplate <class _Tp, class _Up> 12840b57cec5SDimitry Andric_LIBCPP_INLINE_VISIBILITY constexpr 12850b57cec5SDimitry Andric_EnableIf< 12860b57cec5SDimitry Andric is_convertible_v<decltype(_VSTD::declval<const _Tp&>() < 12870b57cec5SDimitry Andric _VSTD::declval<const _Up&>()), bool>, 12880b57cec5SDimitry Andric bool 12890b57cec5SDimitry Andric> 12900b57cec5SDimitry Andricoperator<(const _Tp& __v, const optional<_Up>& __x) 12910b57cec5SDimitry Andric{ 12920b57cec5SDimitry Andric return static_cast<bool>(__x) ? __v < *__x : false; 12930b57cec5SDimitry Andric} 12940b57cec5SDimitry Andric 12950b57cec5SDimitry Andrictemplate <class _Tp, class _Up> 12960b57cec5SDimitry Andric_LIBCPP_INLINE_VISIBILITY constexpr 12970b57cec5SDimitry Andric_EnableIf< 12980b57cec5SDimitry Andric is_convertible_v<decltype(_VSTD::declval<const _Tp&>() <= 12990b57cec5SDimitry Andric _VSTD::declval<const _Up&>()), bool>, 13000b57cec5SDimitry Andric bool 13010b57cec5SDimitry Andric> 13020b57cec5SDimitry Andricoperator<=(const optional<_Tp>& __x, const _Up& __v) 13030b57cec5SDimitry Andric{ 13040b57cec5SDimitry Andric return static_cast<bool>(__x) ? *__x <= __v : true; 13050b57cec5SDimitry Andric} 13060b57cec5SDimitry Andric 13070b57cec5SDimitry Andrictemplate <class _Tp, class _Up> 13080b57cec5SDimitry Andric_LIBCPP_INLINE_VISIBILITY constexpr 13090b57cec5SDimitry Andric_EnableIf< 13100b57cec5SDimitry Andric is_convertible_v<decltype(_VSTD::declval<const _Tp&>() <= 13110b57cec5SDimitry Andric _VSTD::declval<const _Up&>()), bool>, 13120b57cec5SDimitry Andric bool 13130b57cec5SDimitry Andric> 13140b57cec5SDimitry Andricoperator<=(const _Tp& __v, const optional<_Up>& __x) 13150b57cec5SDimitry Andric{ 13160b57cec5SDimitry Andric return static_cast<bool>(__x) ? __v <= *__x : false; 13170b57cec5SDimitry Andric} 13180b57cec5SDimitry Andric 13190b57cec5SDimitry Andrictemplate <class _Tp, class _Up> 13200b57cec5SDimitry Andric_LIBCPP_INLINE_VISIBILITY constexpr 13210b57cec5SDimitry Andric_EnableIf< 13220b57cec5SDimitry Andric is_convertible_v<decltype(_VSTD::declval<const _Tp&>() > 13230b57cec5SDimitry Andric _VSTD::declval<const _Up&>()), bool>, 13240b57cec5SDimitry Andric bool 13250b57cec5SDimitry Andric> 13260b57cec5SDimitry Andricoperator>(const optional<_Tp>& __x, const _Up& __v) 13270b57cec5SDimitry Andric{ 13280b57cec5SDimitry Andric return static_cast<bool>(__x) ? *__x > __v : false; 13290b57cec5SDimitry Andric} 13300b57cec5SDimitry Andric 13310b57cec5SDimitry Andrictemplate <class _Tp, class _Up> 13320b57cec5SDimitry Andric_LIBCPP_INLINE_VISIBILITY constexpr 13330b57cec5SDimitry Andric_EnableIf< 13340b57cec5SDimitry Andric is_convertible_v<decltype(_VSTD::declval<const _Tp&>() > 13350b57cec5SDimitry Andric _VSTD::declval<const _Up&>()), bool>, 13360b57cec5SDimitry Andric bool 13370b57cec5SDimitry Andric> 13380b57cec5SDimitry Andricoperator>(const _Tp& __v, const optional<_Up>& __x) 13390b57cec5SDimitry Andric{ 13400b57cec5SDimitry Andric return static_cast<bool>(__x) ? __v > *__x : true; 13410b57cec5SDimitry Andric} 13420b57cec5SDimitry Andric 13430b57cec5SDimitry Andrictemplate <class _Tp, class _Up> 13440b57cec5SDimitry Andric_LIBCPP_INLINE_VISIBILITY constexpr 13450b57cec5SDimitry Andric_EnableIf< 13460b57cec5SDimitry Andric is_convertible_v<decltype(_VSTD::declval<const _Tp&>() >= 13470b57cec5SDimitry Andric _VSTD::declval<const _Up&>()), bool>, 13480b57cec5SDimitry Andric bool 13490b57cec5SDimitry Andric> 13500b57cec5SDimitry Andricoperator>=(const optional<_Tp>& __x, const _Up& __v) 13510b57cec5SDimitry Andric{ 13520b57cec5SDimitry Andric return static_cast<bool>(__x) ? *__x >= __v : false; 13530b57cec5SDimitry Andric} 13540b57cec5SDimitry Andric 13550b57cec5SDimitry Andrictemplate <class _Tp, class _Up> 13560b57cec5SDimitry Andric_LIBCPP_INLINE_VISIBILITY constexpr 13570b57cec5SDimitry Andric_EnableIf< 13580b57cec5SDimitry Andric is_convertible_v<decltype(_VSTD::declval<const _Tp&>() >= 13590b57cec5SDimitry Andric _VSTD::declval<const _Up&>()), bool>, 13600b57cec5SDimitry Andric bool 13610b57cec5SDimitry Andric> 13620b57cec5SDimitry Andricoperator>=(const _Tp& __v, const optional<_Up>& __x) 13630b57cec5SDimitry Andric{ 13640b57cec5SDimitry Andric return static_cast<bool>(__x) ? __v >= *__x : true; 13650b57cec5SDimitry Andric} 13660b57cec5SDimitry Andric 13670b57cec5SDimitry Andric 13680b57cec5SDimitry Andrictemplate <class _Tp> 13690b57cec5SDimitry Andricinline _LIBCPP_INLINE_VISIBILITY 13700b57cec5SDimitry Andric_EnableIf< 13710b57cec5SDimitry Andric is_move_constructible_v<_Tp> && is_swappable_v<_Tp>, 13720b57cec5SDimitry Andric void 13730b57cec5SDimitry Andric> 13740b57cec5SDimitry Andricswap(optional<_Tp>& __x, optional<_Tp>& __y) noexcept(noexcept(__x.swap(__y))) 13750b57cec5SDimitry Andric{ 13760b57cec5SDimitry Andric __x.swap(__y); 13770b57cec5SDimitry Andric} 13780b57cec5SDimitry Andric 13790b57cec5SDimitry Andrictemplate <class _Tp> 13800b57cec5SDimitry Andric_LIBCPP_INLINE_VISIBILITY constexpr 13810b57cec5SDimitry Andricoptional<decay_t<_Tp>> make_optional(_Tp&& __v) 13820b57cec5SDimitry Andric{ 13830b57cec5SDimitry Andric return optional<decay_t<_Tp>>(_VSTD::forward<_Tp>(__v)); 13840b57cec5SDimitry Andric} 13850b57cec5SDimitry Andric 13860b57cec5SDimitry Andrictemplate <class _Tp, class... _Args> 13870b57cec5SDimitry Andric_LIBCPP_INLINE_VISIBILITY constexpr 13880b57cec5SDimitry Andricoptional<_Tp> make_optional(_Args&&... __args) 13890b57cec5SDimitry Andric{ 13900b57cec5SDimitry Andric return optional<_Tp>(in_place, _VSTD::forward<_Args>(__args)...); 13910b57cec5SDimitry Andric} 13920b57cec5SDimitry Andric 13930b57cec5SDimitry Andrictemplate <class _Tp, class _Up, class... _Args> 13940b57cec5SDimitry Andric_LIBCPP_INLINE_VISIBILITY constexpr 13950b57cec5SDimitry Andricoptional<_Tp> make_optional(initializer_list<_Up> __il, _Args&&... __args) 13960b57cec5SDimitry Andric{ 13970b57cec5SDimitry Andric return optional<_Tp>(in_place, __il, _VSTD::forward<_Args>(__args)...); 13980b57cec5SDimitry Andric} 13990b57cec5SDimitry Andric 14000b57cec5SDimitry Andrictemplate <class _Tp> 14010b57cec5SDimitry Andricstruct _LIBCPP_TEMPLATE_VIS hash< 14020b57cec5SDimitry Andric __enable_hash_helper<optional<_Tp>, remove_const_t<_Tp>> 14030b57cec5SDimitry Andric> 14040b57cec5SDimitry Andric{ 14050b57cec5SDimitry Andric typedef optional<_Tp> argument_type; 14060b57cec5SDimitry Andric typedef size_t result_type; 14070b57cec5SDimitry Andric 14080b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY 14090b57cec5SDimitry Andric result_type operator()(const argument_type& __opt) const 14100b57cec5SDimitry Andric { 14110b57cec5SDimitry Andric return static_cast<bool>(__opt) ? hash<remove_const_t<_Tp>>()(*__opt) : 0; 14120b57cec5SDimitry Andric } 14130b57cec5SDimitry Andric}; 14140b57cec5SDimitry Andric 14150b57cec5SDimitry Andric_LIBCPP_END_NAMESPACE_STD 14160b57cec5SDimitry Andric 14170b57cec5SDimitry Andric#endif // _LIBCPP_STD_VER > 14 14180b57cec5SDimitry Andric 14190b57cec5SDimitry Andric_LIBCPP_POP_MACROS 14200b57cec5SDimitry Andric 14210b57cec5SDimitry Andric#endif // _LIBCPP_OPTIONAL 1422