1*38fd1498Szrj// <optional> -*- C++ -*- 2*38fd1498Szrj 3*38fd1498Szrj// Copyright (C) 2013-2018 Free Software Foundation, Inc. 4*38fd1498Szrj// 5*38fd1498Szrj// This file is part of the GNU ISO C++ Library. This library is free 6*38fd1498Szrj// software; you can redistribute it and/or modify it under the 7*38fd1498Szrj// terms of the GNU General Public License as published by the 8*38fd1498Szrj// Free Software Foundation; either version 3, or (at your option) 9*38fd1498Szrj// any later version. 10*38fd1498Szrj 11*38fd1498Szrj// This library is distributed in the hope that it will be useful, 12*38fd1498Szrj// but WITHOUT ANY WARRANTY; without even the implied warranty of 13*38fd1498Szrj// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14*38fd1498Szrj// GNU General Public License for more details. 15*38fd1498Szrj 16*38fd1498Szrj// Under Section 7 of GPL version 3, you are granted additional 17*38fd1498Szrj// permissions described in the GCC Runtime Library Exception, version 18*38fd1498Szrj// 3.1, as published by the Free Software Foundation. 19*38fd1498Szrj 20*38fd1498Szrj// You should have received a copy of the GNU General Public License and 21*38fd1498Szrj// a copy of the GCC Runtime Library Exception along with this program; 22*38fd1498Szrj// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see 23*38fd1498Szrj// <http://www.gnu.org/licenses/>. 24*38fd1498Szrj 25*38fd1498Szrj/** @file experimental/optional 26*38fd1498Szrj * This is a TS C++ Library header. 27*38fd1498Szrj */ 28*38fd1498Szrj 29*38fd1498Szrj#ifndef _GLIBCXX_EXPERIMENTAL_OPTIONAL 30*38fd1498Szrj#define _GLIBCXX_EXPERIMENTAL_OPTIONAL 1 31*38fd1498Szrj 32*38fd1498Szrj/** 33*38fd1498Szrj * @defgroup experimental Experimental 34*38fd1498Szrj * 35*38fd1498Szrj * Components specified by various Technical Specifications. 36*38fd1498Szrj * 37*38fd1498Szrj * As indicated by the std::experimental namespace and the header paths, 38*38fd1498Szrj * the contents of these Technical Specifications are experimental and not 39*38fd1498Szrj * part of the C++ standard. As such the interfaces and implementations may 40*38fd1498Szrj * change in the future, and there is <STRONG> no guarantee of compatibility 41*38fd1498Szrj * between different GCC releases </STRONG> for these features. 42*38fd1498Szrj */ 43*38fd1498Szrj 44*38fd1498Szrj#if __cplusplus >= 201402L 45*38fd1498Szrj 46*38fd1498Szrj#include <utility> 47*38fd1498Szrj#include <type_traits> 48*38fd1498Szrj#include <stdexcept> 49*38fd1498Szrj#include <new> 50*38fd1498Szrj#include <initializer_list> 51*38fd1498Szrj#include <bits/functexcept.h> 52*38fd1498Szrj#include <bits/functional_hash.h> 53*38fd1498Szrj#include <bits/enable_special_members.h> 54*38fd1498Szrj#include <experimental/bits/lfts_config.h> 55*38fd1498Szrj 56*38fd1498Szrjnamespace std _GLIBCXX_VISIBILITY(default) 57*38fd1498Szrj{ 58*38fd1498Szrj_GLIBCXX_BEGIN_NAMESPACE_VERSION 59*38fd1498Szrj 60*38fd1498Szrjnamespace experimental 61*38fd1498Szrj{ 62*38fd1498Szrjinline namespace fundamentals_v1 63*38fd1498Szrj{ 64*38fd1498Szrj /** 65*38fd1498Szrj * @defgroup optional Optional values 66*38fd1498Szrj * @ingroup experimental 67*38fd1498Szrj * 68*38fd1498Szrj * Class template for optional values and surrounding facilities, as 69*38fd1498Szrj * described in n3793 "A proposal to add a utility class to represent 70*38fd1498Szrj * optional objects (Revision 5)". 71*38fd1498Szrj * 72*38fd1498Szrj * @{ 73*38fd1498Szrj */ 74*38fd1498Szrj 75*38fd1498Szrj#define __cpp_lib_experimental_optional 201411 76*38fd1498Szrj 77*38fd1498Szrj // All subsequent [X.Y.n] references are against n3793. 78*38fd1498Szrj 79*38fd1498Szrj // [X.Y.4] 80*38fd1498Szrj template<typename _Tp> 81*38fd1498Szrj class optional; 82*38fd1498Szrj 83*38fd1498Szrj // [X.Y.5] 84*38fd1498Szrj /// Tag type for in-place construction. 85*38fd1498Szrj struct in_place_t { }; 86*38fd1498Szrj 87*38fd1498Szrj /// Tag for in-place construction. 88*38fd1498Szrj constexpr in_place_t in_place { }; 89*38fd1498Szrj 90*38fd1498Szrj // [X.Y.6] 91*38fd1498Szrj /// Tag type to disengage optional objects. 92*38fd1498Szrj struct nullopt_t 93*38fd1498Szrj { 94*38fd1498Szrj // Do not user-declare default constructor at all for 95*38fd1498Szrj // optional_value = {} syntax to work. 96*38fd1498Szrj // nullopt_t() = delete; 97*38fd1498Szrj 98*38fd1498Szrj // Used for constructing nullopt. 99*38fd1498Szrj enum class _Construct { _Token }; 100*38fd1498Szrj 101*38fd1498Szrj // Must be constexpr for nullopt_t to be literal. 102*38fd1498Szrj explicit constexpr nullopt_t(_Construct) { } 103*38fd1498Szrj }; 104*38fd1498Szrj 105*38fd1498Szrj // [X.Y.6] 106*38fd1498Szrj /// Tag to disengage optional objects. 107*38fd1498Szrj constexpr nullopt_t nullopt { nullopt_t::_Construct::_Token }; 108*38fd1498Szrj 109*38fd1498Szrj // [X.Y.7] 110*38fd1498Szrj /** 111*38fd1498Szrj * @brief Exception class thrown when a disengaged optional object is 112*38fd1498Szrj * dereferenced. 113*38fd1498Szrj * @ingroup exceptions 114*38fd1498Szrj */ 115*38fd1498Szrj class bad_optional_access : public logic_error 116*38fd1498Szrj { 117*38fd1498Szrj public: 118*38fd1498Szrj bad_optional_access() : logic_error("bad optional access") { } 119*38fd1498Szrj 120*38fd1498Szrj // XXX This constructor is non-standard. Should not be inline 121*38fd1498Szrj explicit bad_optional_access(const char* __arg) : logic_error(__arg) { } 122*38fd1498Szrj 123*38fd1498Szrj virtual ~bad_optional_access() noexcept = default; 124*38fd1498Szrj }; 125*38fd1498Szrj 126*38fd1498Szrj void 127*38fd1498Szrj __throw_bad_optional_access(const char*) 128*38fd1498Szrj __attribute__((__noreturn__)); 129*38fd1498Szrj 130*38fd1498Szrj // XXX Does not belong here. 131*38fd1498Szrj inline void 132*38fd1498Szrj __throw_bad_optional_access(const char* __s) 133*38fd1498Szrj { _GLIBCXX_THROW_OR_ABORT(bad_optional_access(__s)); } 134*38fd1498Szrj 135*38fd1498Szrj#ifndef __cpp_lib_addressof_constexpr 136*38fd1498Szrj template<typename _Tp, typename = void> 137*38fd1498Szrj struct _Has_addressof_mem : std::false_type { }; 138*38fd1498Szrj 139*38fd1498Szrj template<typename _Tp> 140*38fd1498Szrj struct _Has_addressof_mem<_Tp, 141*38fd1498Szrj __void_t<decltype( std::declval<const _Tp&>().operator&() )> 142*38fd1498Szrj > 143*38fd1498Szrj : std::true_type { }; 144*38fd1498Szrj 145*38fd1498Szrj template<typename _Tp, typename = void> 146*38fd1498Szrj struct _Has_addressof_free : std::false_type { }; 147*38fd1498Szrj 148*38fd1498Szrj template<typename _Tp> 149*38fd1498Szrj struct _Has_addressof_free<_Tp, 150*38fd1498Szrj __void_t<decltype( operator&(std::declval<const _Tp&>()) )> 151*38fd1498Szrj > 152*38fd1498Szrj : std::true_type { }; 153*38fd1498Szrj 154*38fd1498Szrj /** 155*38fd1498Szrj * @brief Trait that detects the presence of an overloaded unary operator&. 156*38fd1498Szrj * 157*38fd1498Szrj * Practically speaking this detects the presence of such an operator when 158*38fd1498Szrj * called on a const-qualified lvalue (e.g. 159*38fd1498Szrj * declval<const _Tp&>().operator&()). 160*38fd1498Szrj */ 161*38fd1498Szrj template<typename _Tp> 162*38fd1498Szrj struct _Has_addressof 163*38fd1498Szrj : std::__or_<_Has_addressof_mem<_Tp>, _Has_addressof_free<_Tp>>::type 164*38fd1498Szrj { }; 165*38fd1498Szrj 166*38fd1498Szrj /** 167*38fd1498Szrj * @brief An overload that attempts to take the address of an lvalue as a 168*38fd1498Szrj * constant expression. Falls back to __addressof in the presence of an 169*38fd1498Szrj * overloaded addressof operator (unary operator&), in which case the call 170*38fd1498Szrj * will not be a constant expression. 171*38fd1498Szrj */ 172*38fd1498Szrj template<typename _Tp> 173*38fd1498Szrj constexpr 174*38fd1498Szrj enable_if_t<!_Has_addressof<_Tp>::value, _Tp*> 175*38fd1498Szrj __constexpr_addressof(_Tp& __t) 176*38fd1498Szrj { return &__t; } 177*38fd1498Szrj 178*38fd1498Szrj /** 179*38fd1498Szrj * @brief Fallback overload that defers to __addressof. 180*38fd1498Szrj */ 181*38fd1498Szrj template<typename _Tp> 182*38fd1498Szrj inline 183*38fd1498Szrj enable_if_t<_Has_addressof<_Tp>::value, _Tp*> 184*38fd1498Szrj __constexpr_addressof(_Tp& __t) 185*38fd1498Szrj { return std::__addressof(__t); } 186*38fd1498Szrj#endif // __cpp_lib_addressof_constexpr 187*38fd1498Szrj 188*38fd1498Szrj /** 189*38fd1498Szrj * @brief Class template that holds the necessary state for @ref optional 190*38fd1498Szrj * and that has the responsibility for construction and the special members. 191*38fd1498Szrj * 192*38fd1498Szrj * Such a separate base class template is necessary in order to 193*38fd1498Szrj * conditionally enable the special members (e.g. copy/move constructors). 194*38fd1498Szrj * Note that this means that @ref _Optional_base implements the 195*38fd1498Szrj * functionality for copy and move assignment, but not for converting 196*38fd1498Szrj * assignment. 197*38fd1498Szrj * 198*38fd1498Szrj * @see optional, _Enable_special_members 199*38fd1498Szrj */ 200*38fd1498Szrj template<typename _Tp, bool _ShouldProvideDestructor = 201*38fd1498Szrj !is_trivially_destructible<_Tp>::value> 202*38fd1498Szrj class _Optional_base 203*38fd1498Szrj { 204*38fd1498Szrj private: 205*38fd1498Szrj // Remove const to avoid prohibition of reusing object storage for 206*38fd1498Szrj // const-qualified types in [3.8/9]. This is strictly internal 207*38fd1498Szrj // and even optional itself is oblivious to it. 208*38fd1498Szrj using _Stored_type = remove_const_t<_Tp>; 209*38fd1498Szrj 210*38fd1498Szrj public: 211*38fd1498Szrj // [X.Y.4.1] Constructors. 212*38fd1498Szrj 213*38fd1498Szrj // Constructors for disengaged optionals. 214*38fd1498Szrj constexpr _Optional_base() noexcept 215*38fd1498Szrj : _M_empty{} { } 216*38fd1498Szrj 217*38fd1498Szrj constexpr _Optional_base(nullopt_t) noexcept 218*38fd1498Szrj : _Optional_base{} { } 219*38fd1498Szrj 220*38fd1498Szrj // Constructors for engaged optionals. 221*38fd1498Szrj template<typename... _Args> 222*38fd1498Szrj constexpr explicit _Optional_base(in_place_t, _Args&&... __args) 223*38fd1498Szrj : _M_payload(std::forward<_Args>(__args)...), _M_engaged(true) { } 224*38fd1498Szrj 225*38fd1498Szrj template<typename _Up, typename... _Args, 226*38fd1498Szrj enable_if_t<is_constructible<_Tp, 227*38fd1498Szrj initializer_list<_Up>&, 228*38fd1498Szrj _Args&&...>::value, 229*38fd1498Szrj int>...> 230*38fd1498Szrj constexpr explicit _Optional_base(in_place_t, 231*38fd1498Szrj initializer_list<_Up> __il, 232*38fd1498Szrj _Args&&... __args) 233*38fd1498Szrj : _M_payload(__il, std::forward<_Args>(__args)...), 234*38fd1498Szrj _M_engaged(true) { } 235*38fd1498Szrj 236*38fd1498Szrj // Copy and move constructors. 237*38fd1498Szrj _Optional_base(const _Optional_base& __other) 238*38fd1498Szrj { 239*38fd1498Szrj if (__other._M_engaged) 240*38fd1498Szrj this->_M_construct(__other._M_get()); 241*38fd1498Szrj } 242*38fd1498Szrj 243*38fd1498Szrj _Optional_base(_Optional_base&& __other) 244*38fd1498Szrj noexcept(is_nothrow_move_constructible<_Tp>()) 245*38fd1498Szrj { 246*38fd1498Szrj if (__other._M_engaged) 247*38fd1498Szrj this->_M_construct(std::move(__other._M_get())); 248*38fd1498Szrj } 249*38fd1498Szrj 250*38fd1498Szrj // [X.Y.4.3] (partly) Assignment. 251*38fd1498Szrj _Optional_base& 252*38fd1498Szrj operator=(const _Optional_base& __other) 253*38fd1498Szrj { 254*38fd1498Szrj if (this->_M_engaged && __other._M_engaged) 255*38fd1498Szrj this->_M_get() = __other._M_get(); 256*38fd1498Szrj else 257*38fd1498Szrj { 258*38fd1498Szrj if (__other._M_engaged) 259*38fd1498Szrj this->_M_construct(__other._M_get()); 260*38fd1498Szrj else 261*38fd1498Szrj this->_M_reset(); 262*38fd1498Szrj } 263*38fd1498Szrj 264*38fd1498Szrj return *this; 265*38fd1498Szrj } 266*38fd1498Szrj 267*38fd1498Szrj _Optional_base& 268*38fd1498Szrj operator=(_Optional_base&& __other) 269*38fd1498Szrj noexcept(__and_<is_nothrow_move_constructible<_Tp>, 270*38fd1498Szrj is_nothrow_move_assignable<_Tp>>()) 271*38fd1498Szrj { 272*38fd1498Szrj if (this->_M_engaged && __other._M_engaged) 273*38fd1498Szrj this->_M_get() = std::move(__other._M_get()); 274*38fd1498Szrj else 275*38fd1498Szrj { 276*38fd1498Szrj if (__other._M_engaged) 277*38fd1498Szrj this->_M_construct(std::move(__other._M_get())); 278*38fd1498Szrj else 279*38fd1498Szrj this->_M_reset(); 280*38fd1498Szrj } 281*38fd1498Szrj return *this; 282*38fd1498Szrj } 283*38fd1498Szrj 284*38fd1498Szrj // [X.Y.4.2] Destructor. 285*38fd1498Szrj ~_Optional_base() 286*38fd1498Szrj { 287*38fd1498Szrj if (this->_M_engaged) 288*38fd1498Szrj this->_M_payload.~_Stored_type(); 289*38fd1498Szrj } 290*38fd1498Szrj 291*38fd1498Szrj // The following functionality is also needed by optional, hence the 292*38fd1498Szrj // protected accessibility. 293*38fd1498Szrj protected: 294*38fd1498Szrj constexpr bool _M_is_engaged() const noexcept 295*38fd1498Szrj { return this->_M_engaged; } 296*38fd1498Szrj 297*38fd1498Szrj // The _M_get operations have _M_engaged as a precondition. 298*38fd1498Szrj constexpr _Tp& 299*38fd1498Szrj _M_get() noexcept 300*38fd1498Szrj { return _M_payload; } 301*38fd1498Szrj 302*38fd1498Szrj constexpr const _Tp& 303*38fd1498Szrj _M_get() const noexcept 304*38fd1498Szrj { return _M_payload; } 305*38fd1498Szrj 306*38fd1498Szrj // The _M_construct operation has !_M_engaged as a precondition 307*38fd1498Szrj // while _M_destruct has _M_engaged as a precondition. 308*38fd1498Szrj template<typename... _Args> 309*38fd1498Szrj void 310*38fd1498Szrj _M_construct(_Args&&... __args) 311*38fd1498Szrj noexcept(is_nothrow_constructible<_Stored_type, _Args...>()) 312*38fd1498Szrj { 313*38fd1498Szrj ::new (std::__addressof(this->_M_payload)) 314*38fd1498Szrj _Stored_type(std::forward<_Args>(__args)...); 315*38fd1498Szrj this->_M_engaged = true; 316*38fd1498Szrj } 317*38fd1498Szrj 318*38fd1498Szrj void 319*38fd1498Szrj _M_destruct() 320*38fd1498Szrj { 321*38fd1498Szrj this->_M_engaged = false; 322*38fd1498Szrj this->_M_payload.~_Stored_type(); 323*38fd1498Szrj } 324*38fd1498Szrj 325*38fd1498Szrj // _M_reset is a 'safe' operation with no precondition. 326*38fd1498Szrj void 327*38fd1498Szrj _M_reset() 328*38fd1498Szrj { 329*38fd1498Szrj if (this->_M_engaged) 330*38fd1498Szrj this->_M_destruct(); 331*38fd1498Szrj } 332*38fd1498Szrj 333*38fd1498Szrj private: 334*38fd1498Szrj struct _Empty_byte { }; 335*38fd1498Szrj union { 336*38fd1498Szrj _Empty_byte _M_empty; 337*38fd1498Szrj _Stored_type _M_payload; 338*38fd1498Szrj }; 339*38fd1498Szrj bool _M_engaged = false; 340*38fd1498Szrj }; 341*38fd1498Szrj 342*38fd1498Szrj /// Partial specialization that is exactly identical to the primary template 343*38fd1498Szrj /// save for not providing a destructor, to fulfill triviality requirements. 344*38fd1498Szrj template<typename _Tp> 345*38fd1498Szrj class _Optional_base<_Tp, false> 346*38fd1498Szrj { 347*38fd1498Szrj private: 348*38fd1498Szrj using _Stored_type = remove_const_t<_Tp>; 349*38fd1498Szrj 350*38fd1498Szrj public: 351*38fd1498Szrj constexpr _Optional_base() noexcept 352*38fd1498Szrj : _M_empty{} { } 353*38fd1498Szrj 354*38fd1498Szrj constexpr _Optional_base(nullopt_t) noexcept 355*38fd1498Szrj : _Optional_base{} { } 356*38fd1498Szrj 357*38fd1498Szrj template<typename... _Args> 358*38fd1498Szrj constexpr explicit _Optional_base(in_place_t, _Args&&... __args) 359*38fd1498Szrj : _M_payload(std::forward<_Args>(__args)...), _M_engaged(true) { } 360*38fd1498Szrj 361*38fd1498Szrj template<typename _Up, typename... _Args, 362*38fd1498Szrj enable_if_t<is_constructible<_Tp, 363*38fd1498Szrj initializer_list<_Up>&, 364*38fd1498Szrj _Args&&...>::value, 365*38fd1498Szrj int>...> 366*38fd1498Szrj constexpr explicit _Optional_base(in_place_t, 367*38fd1498Szrj initializer_list<_Up> __il, 368*38fd1498Szrj _Args&&... __args) 369*38fd1498Szrj : _M_payload(__il, std::forward<_Args>(__args)...), 370*38fd1498Szrj _M_engaged(true) { } 371*38fd1498Szrj 372*38fd1498Szrj _Optional_base(const _Optional_base& __other) 373*38fd1498Szrj { 374*38fd1498Szrj if (__other._M_engaged) 375*38fd1498Szrj this->_M_construct(__other._M_get()); 376*38fd1498Szrj } 377*38fd1498Szrj 378*38fd1498Szrj _Optional_base(_Optional_base&& __other) 379*38fd1498Szrj noexcept(is_nothrow_move_constructible<_Tp>()) 380*38fd1498Szrj { 381*38fd1498Szrj if (__other._M_engaged) 382*38fd1498Szrj this->_M_construct(std::move(__other._M_get())); 383*38fd1498Szrj } 384*38fd1498Szrj 385*38fd1498Szrj _Optional_base& 386*38fd1498Szrj operator=(const _Optional_base& __other) 387*38fd1498Szrj { 388*38fd1498Szrj if (this->_M_engaged && __other._M_engaged) 389*38fd1498Szrj this->_M_get() = __other._M_get(); 390*38fd1498Szrj else 391*38fd1498Szrj { 392*38fd1498Szrj if (__other._M_engaged) 393*38fd1498Szrj this->_M_construct(__other._M_get()); 394*38fd1498Szrj else 395*38fd1498Szrj this->_M_reset(); 396*38fd1498Szrj } 397*38fd1498Szrj return *this; 398*38fd1498Szrj } 399*38fd1498Szrj 400*38fd1498Szrj _Optional_base& 401*38fd1498Szrj operator=(_Optional_base&& __other) 402*38fd1498Szrj noexcept(__and_<is_nothrow_move_constructible<_Tp>, 403*38fd1498Szrj is_nothrow_move_assignable<_Tp>>()) 404*38fd1498Szrj { 405*38fd1498Szrj if (this->_M_engaged && __other._M_engaged) 406*38fd1498Szrj this->_M_get() = std::move(__other._M_get()); 407*38fd1498Szrj else 408*38fd1498Szrj { 409*38fd1498Szrj if (__other._M_engaged) 410*38fd1498Szrj this->_M_construct(std::move(__other._M_get())); 411*38fd1498Szrj else 412*38fd1498Szrj this->_M_reset(); 413*38fd1498Szrj } 414*38fd1498Szrj return *this; 415*38fd1498Szrj } 416*38fd1498Szrj 417*38fd1498Szrj // Sole difference 418*38fd1498Szrj // ~_Optional_base() noexcept = default; 419*38fd1498Szrj 420*38fd1498Szrj protected: 421*38fd1498Szrj constexpr bool _M_is_engaged() const noexcept 422*38fd1498Szrj { return this->_M_engaged; } 423*38fd1498Szrj 424*38fd1498Szrj _Tp& 425*38fd1498Szrj _M_get() noexcept 426*38fd1498Szrj { return _M_payload; } 427*38fd1498Szrj 428*38fd1498Szrj constexpr const _Tp& 429*38fd1498Szrj _M_get() const noexcept 430*38fd1498Szrj { return _M_payload; } 431*38fd1498Szrj 432*38fd1498Szrj template<typename... _Args> 433*38fd1498Szrj void 434*38fd1498Szrj _M_construct(_Args&&... __args) 435*38fd1498Szrj noexcept(is_nothrow_constructible<_Stored_type, _Args...>()) 436*38fd1498Szrj { 437*38fd1498Szrj ::new (std::__addressof(this->_M_payload)) 438*38fd1498Szrj _Stored_type(std::forward<_Args>(__args)...); 439*38fd1498Szrj this->_M_engaged = true; 440*38fd1498Szrj } 441*38fd1498Szrj 442*38fd1498Szrj void 443*38fd1498Szrj _M_destruct() 444*38fd1498Szrj { 445*38fd1498Szrj this->_M_engaged = false; 446*38fd1498Szrj this->_M_payload.~_Stored_type(); 447*38fd1498Szrj } 448*38fd1498Szrj 449*38fd1498Szrj void 450*38fd1498Szrj _M_reset() 451*38fd1498Szrj { 452*38fd1498Szrj if (this->_M_engaged) 453*38fd1498Szrj this->_M_destruct(); 454*38fd1498Szrj } 455*38fd1498Szrj 456*38fd1498Szrj private: 457*38fd1498Szrj struct _Empty_byte { }; 458*38fd1498Szrj union 459*38fd1498Szrj { 460*38fd1498Szrj _Empty_byte _M_empty; 461*38fd1498Szrj _Stored_type _M_payload; 462*38fd1498Szrj }; 463*38fd1498Szrj bool _M_engaged = false; 464*38fd1498Szrj }; 465*38fd1498Szrj 466*38fd1498Szrj template<typename _Tp> 467*38fd1498Szrj class optional; 468*38fd1498Szrj 469*38fd1498Szrj template<typename _Tp, typename _Up> 470*38fd1498Szrj using __converts_from_optional = 471*38fd1498Szrj __or_<is_constructible<_Tp, const optional<_Up>&>, 472*38fd1498Szrj is_constructible<_Tp, optional<_Up>&>, 473*38fd1498Szrj is_constructible<_Tp, const optional<_Up>&&>, 474*38fd1498Szrj is_constructible<_Tp, optional<_Up>&&>, 475*38fd1498Szrj is_convertible<const optional<_Up>&, _Tp>, 476*38fd1498Szrj is_convertible<optional<_Up>&, _Tp>, 477*38fd1498Szrj is_convertible<const optional<_Up>&&, _Tp>, 478*38fd1498Szrj is_convertible<optional<_Up>&&, _Tp>>; 479*38fd1498Szrj 480*38fd1498Szrj template<typename _Tp, typename _Up> 481*38fd1498Szrj using __assigns_from_optional = 482*38fd1498Szrj __or_<is_assignable<_Tp&, const optional<_Up>&>, 483*38fd1498Szrj is_assignable<_Tp&, optional<_Up>&>, 484*38fd1498Szrj is_assignable<_Tp&, const optional<_Up>&&>, 485*38fd1498Szrj is_assignable<_Tp&, optional<_Up>&&>>; 486*38fd1498Szrj 487*38fd1498Szrj /** 488*38fd1498Szrj * @brief Class template for optional values. 489*38fd1498Szrj */ 490*38fd1498Szrj template<typename _Tp> 491*38fd1498Szrj class optional 492*38fd1498Szrj : private _Optional_base<_Tp>, 493*38fd1498Szrj private _Enable_copy_move< 494*38fd1498Szrj // Copy constructor. 495*38fd1498Szrj is_copy_constructible<_Tp>::value, 496*38fd1498Szrj // Copy assignment. 497*38fd1498Szrj __and_<is_copy_constructible<_Tp>, is_copy_assignable<_Tp>>::value, 498*38fd1498Szrj // Move constructor. 499*38fd1498Szrj is_move_constructible<_Tp>::value, 500*38fd1498Szrj // Move assignment. 501*38fd1498Szrj __and_<is_move_constructible<_Tp>, is_move_assignable<_Tp>>::value, 502*38fd1498Szrj // Unique tag type. 503*38fd1498Szrj optional<_Tp>> 504*38fd1498Szrj { 505*38fd1498Szrj static_assert(__and_<__not_<is_same<remove_cv_t<_Tp>, nullopt_t>>, 506*38fd1498Szrj __not_<is_same<remove_cv_t<_Tp>, in_place_t>>, 507*38fd1498Szrj __not_<is_reference<_Tp>>>(), 508*38fd1498Szrj "Invalid instantiation of optional<T>"); 509*38fd1498Szrj 510*38fd1498Szrj private: 511*38fd1498Szrj using _Base = _Optional_base<_Tp>; 512*38fd1498Szrj 513*38fd1498Szrj public: 514*38fd1498Szrj using value_type = _Tp; 515*38fd1498Szrj 516*38fd1498Szrj // _Optional_base has the responsibility for construction. 517*38fd1498Szrj using _Base::_Base; 518*38fd1498Szrj 519*38fd1498Szrj constexpr optional() = default; 520*38fd1498Szrj // Converting constructors for engaged optionals. 521*38fd1498Szrj template <typename _Up = _Tp, 522*38fd1498Szrj enable_if_t<__and_< 523*38fd1498Szrj __not_<is_same<optional<_Tp>, decay_t<_Up>>>, 524*38fd1498Szrj is_constructible<_Tp, _Up&&>, 525*38fd1498Szrj is_convertible<_Up&&, _Tp> 526*38fd1498Szrj >::value, bool> = true> 527*38fd1498Szrj constexpr optional(_Up&& __t) 528*38fd1498Szrj : _Base(in_place, std::forward<_Up>(__t)) { } 529*38fd1498Szrj 530*38fd1498Szrj template <typename _Up = _Tp, 531*38fd1498Szrj enable_if_t<__and_< 532*38fd1498Szrj __not_<is_same<optional<_Tp>, decay_t<_Up>>>, 533*38fd1498Szrj is_constructible<_Tp, _Up&&>, 534*38fd1498Szrj __not_<is_convertible<_Up&&, _Tp>> 535*38fd1498Szrj >::value, bool> = false> 536*38fd1498Szrj explicit constexpr optional(_Up&& __t) 537*38fd1498Szrj : _Base(in_place, std::forward<_Up>(__t)) { } 538*38fd1498Szrj 539*38fd1498Szrj template <typename _Up, 540*38fd1498Szrj enable_if_t<__and_< 541*38fd1498Szrj __not_<is_same<_Tp, _Up>>, 542*38fd1498Szrj is_constructible<_Tp, const _Up&>, 543*38fd1498Szrj is_convertible<const _Up&, _Tp>, 544*38fd1498Szrj __not_<__converts_from_optional<_Tp, _Up>> 545*38fd1498Szrj >::value, bool> = true> 546*38fd1498Szrj constexpr optional(const optional<_Up>& __t) 547*38fd1498Szrj { 548*38fd1498Szrj if (__t) 549*38fd1498Szrj emplace(*__t); 550*38fd1498Szrj } 551*38fd1498Szrj 552*38fd1498Szrj template <typename _Up, 553*38fd1498Szrj enable_if_t<__and_< 554*38fd1498Szrj __not_<is_same<_Tp, _Up>>, 555*38fd1498Szrj is_constructible<_Tp, const _Up&>, 556*38fd1498Szrj __not_<is_convertible<const _Up&, _Tp>>, 557*38fd1498Szrj __not_<__converts_from_optional<_Tp, _Up>> 558*38fd1498Szrj >::value, bool> = false> 559*38fd1498Szrj explicit constexpr optional(const optional<_Up>& __t) 560*38fd1498Szrj { 561*38fd1498Szrj if (__t) 562*38fd1498Szrj emplace(*__t); 563*38fd1498Szrj } 564*38fd1498Szrj 565*38fd1498Szrj template <typename _Up, 566*38fd1498Szrj enable_if_t<__and_< 567*38fd1498Szrj __not_<is_same<_Tp, _Up>>, 568*38fd1498Szrj is_constructible<_Tp, _Up&&>, 569*38fd1498Szrj is_convertible<_Up&&, _Tp>, 570*38fd1498Szrj __not_<__converts_from_optional<_Tp, _Up>> 571*38fd1498Szrj >::value, bool> = true> 572*38fd1498Szrj constexpr optional(optional<_Up>&& __t) 573*38fd1498Szrj { 574*38fd1498Szrj if (__t) 575*38fd1498Szrj emplace(std::move(*__t)); 576*38fd1498Szrj } 577*38fd1498Szrj 578*38fd1498Szrj template <typename _Up, 579*38fd1498Szrj enable_if_t<__and_< 580*38fd1498Szrj __not_<is_same<_Tp, _Up>>, 581*38fd1498Szrj is_constructible<_Tp, _Up&&>, 582*38fd1498Szrj __not_<is_convertible<_Up&&, _Tp>>, 583*38fd1498Szrj __not_<__converts_from_optional<_Tp, _Up>> 584*38fd1498Szrj >::value, bool> = false> 585*38fd1498Szrj explicit constexpr optional(optional<_Up>&& __t) 586*38fd1498Szrj { 587*38fd1498Szrj if (__t) 588*38fd1498Szrj emplace(std::move(*__t)); 589*38fd1498Szrj } 590*38fd1498Szrj 591*38fd1498Szrj // [X.Y.4.3] (partly) Assignment. 592*38fd1498Szrj optional& 593*38fd1498Szrj operator=(nullopt_t) noexcept 594*38fd1498Szrj { 595*38fd1498Szrj this->_M_reset(); 596*38fd1498Szrj return *this; 597*38fd1498Szrj } 598*38fd1498Szrj 599*38fd1498Szrj template<typename _Up = _Tp> 600*38fd1498Szrj enable_if_t<__and_< 601*38fd1498Szrj __not_<is_same<optional<_Tp>, decay_t<_Up>>>, 602*38fd1498Szrj is_constructible<_Tp, _Up>, 603*38fd1498Szrj __not_<__and_<is_scalar<_Tp>, 604*38fd1498Szrj is_same<_Tp, decay_t<_Up>>>>, 605*38fd1498Szrj is_assignable<_Tp&, _Up>>::value, 606*38fd1498Szrj optional&> 607*38fd1498Szrj operator=(_Up&& __u) 608*38fd1498Szrj { 609*38fd1498Szrj if (this->_M_is_engaged()) 610*38fd1498Szrj this->_M_get() = std::forward<_Up>(__u); 611*38fd1498Szrj else 612*38fd1498Szrj this->_M_construct(std::forward<_Up>(__u)); 613*38fd1498Szrj 614*38fd1498Szrj return *this; 615*38fd1498Szrj } 616*38fd1498Szrj 617*38fd1498Szrj template<typename _Up> 618*38fd1498Szrj enable_if_t<__and_< 619*38fd1498Szrj __not_<is_same<_Tp, _Up>>, 620*38fd1498Szrj is_constructible<_Tp, const _Up&>, 621*38fd1498Szrj is_assignable<_Tp&, _Up>, 622*38fd1498Szrj __not_<__converts_from_optional<_Tp, _Up>>, 623*38fd1498Szrj __not_<__assigns_from_optional<_Tp, _Up>> 624*38fd1498Szrj >::value, 625*38fd1498Szrj optional&> 626*38fd1498Szrj operator=(const optional<_Up>& __u) 627*38fd1498Szrj { 628*38fd1498Szrj if (__u) 629*38fd1498Szrj { 630*38fd1498Szrj if (this->_M_is_engaged()) 631*38fd1498Szrj this->_M_get() = *__u; 632*38fd1498Szrj else 633*38fd1498Szrj this->_M_construct(*__u); 634*38fd1498Szrj } 635*38fd1498Szrj else 636*38fd1498Szrj { 637*38fd1498Szrj this->_M_reset(); 638*38fd1498Szrj } 639*38fd1498Szrj return *this; 640*38fd1498Szrj } 641*38fd1498Szrj 642*38fd1498Szrj template<typename _Up> 643*38fd1498Szrj enable_if_t<__and_< 644*38fd1498Szrj __not_<is_same<_Tp, _Up>>, 645*38fd1498Szrj is_constructible<_Tp, _Up>, 646*38fd1498Szrj is_assignable<_Tp&, _Up>, 647*38fd1498Szrj __not_<__converts_from_optional<_Tp, _Up>>, 648*38fd1498Szrj __not_<__assigns_from_optional<_Tp, _Up>> 649*38fd1498Szrj >::value, 650*38fd1498Szrj optional&> 651*38fd1498Szrj operator=(optional<_Up>&& __u) 652*38fd1498Szrj { 653*38fd1498Szrj if (__u) 654*38fd1498Szrj { 655*38fd1498Szrj if (this->_M_is_engaged()) 656*38fd1498Szrj this->_M_get() = std::move(*__u); 657*38fd1498Szrj else 658*38fd1498Szrj this->_M_construct(std::move(*__u)); 659*38fd1498Szrj } 660*38fd1498Szrj else 661*38fd1498Szrj { 662*38fd1498Szrj this->_M_reset(); 663*38fd1498Szrj } 664*38fd1498Szrj 665*38fd1498Szrj return *this; 666*38fd1498Szrj } 667*38fd1498Szrj 668*38fd1498Szrj template<typename... _Args> 669*38fd1498Szrj enable_if_t<is_constructible<_Tp, _Args&&...>::value> 670*38fd1498Szrj emplace(_Args&&... __args) 671*38fd1498Szrj { 672*38fd1498Szrj this->_M_reset(); 673*38fd1498Szrj this->_M_construct(std::forward<_Args>(__args)...); 674*38fd1498Szrj } 675*38fd1498Szrj 676*38fd1498Szrj template<typename _Up, typename... _Args> 677*38fd1498Szrj enable_if_t<is_constructible<_Tp, initializer_list<_Up>&, 678*38fd1498Szrj _Args&&...>::value> 679*38fd1498Szrj emplace(initializer_list<_Up> __il, _Args&&... __args) 680*38fd1498Szrj { 681*38fd1498Szrj this->_M_reset(); 682*38fd1498Szrj this->_M_construct(__il, std::forward<_Args>(__args)...); 683*38fd1498Szrj } 684*38fd1498Szrj 685*38fd1498Szrj // [X.Y.4.2] Destructor is implicit, implemented in _Optional_base. 686*38fd1498Szrj 687*38fd1498Szrj // [X.Y.4.4] Swap. 688*38fd1498Szrj void 689*38fd1498Szrj swap(optional& __other) 690*38fd1498Szrj noexcept(is_nothrow_move_constructible<_Tp>() 691*38fd1498Szrj && __is_nothrow_swappable<_Tp>::value) 692*38fd1498Szrj { 693*38fd1498Szrj using std::swap; 694*38fd1498Szrj 695*38fd1498Szrj if (this->_M_is_engaged() && __other._M_is_engaged()) 696*38fd1498Szrj swap(this->_M_get(), __other._M_get()); 697*38fd1498Szrj else if (this->_M_is_engaged()) 698*38fd1498Szrj { 699*38fd1498Szrj __other._M_construct(std::move(this->_M_get())); 700*38fd1498Szrj this->_M_destruct(); 701*38fd1498Szrj } 702*38fd1498Szrj else if (__other._M_is_engaged()) 703*38fd1498Szrj { 704*38fd1498Szrj this->_M_construct(std::move(__other._M_get())); 705*38fd1498Szrj __other._M_destruct(); 706*38fd1498Szrj } 707*38fd1498Szrj } 708*38fd1498Szrj 709*38fd1498Szrj // [X.Y.4.5] Observers. 710*38fd1498Szrj constexpr const _Tp* 711*38fd1498Szrj operator->() const 712*38fd1498Szrj { 713*38fd1498Szrj#ifndef __cpp_lib_addressof_constexpr 714*38fd1498Szrj return __constexpr_addressof(this->_M_get()); 715*38fd1498Szrj#else 716*38fd1498Szrj return std::__addressof(this->_M_get()); 717*38fd1498Szrj#endif 718*38fd1498Szrj } 719*38fd1498Szrj 720*38fd1498Szrj _Tp* 721*38fd1498Szrj operator->() 722*38fd1498Szrj { return std::__addressof(this->_M_get()); } 723*38fd1498Szrj 724*38fd1498Szrj constexpr const _Tp& 725*38fd1498Szrj operator*() const& 726*38fd1498Szrj { return this->_M_get(); } 727*38fd1498Szrj 728*38fd1498Szrj constexpr _Tp& 729*38fd1498Szrj operator*()& 730*38fd1498Szrj { return this->_M_get(); } 731*38fd1498Szrj 732*38fd1498Szrj constexpr _Tp&& 733*38fd1498Szrj operator*()&& 734*38fd1498Szrj { return std::move(this->_M_get()); } 735*38fd1498Szrj 736*38fd1498Szrj constexpr const _Tp&& 737*38fd1498Szrj operator*() const&& 738*38fd1498Szrj { return std::move(this->_M_get()); } 739*38fd1498Szrj 740*38fd1498Szrj constexpr explicit operator bool() const noexcept 741*38fd1498Szrj { return this->_M_is_engaged(); } 742*38fd1498Szrj 743*38fd1498Szrj constexpr const _Tp& 744*38fd1498Szrj value() const& 745*38fd1498Szrj { 746*38fd1498Szrj return this->_M_is_engaged() 747*38fd1498Szrj ? this->_M_get() 748*38fd1498Szrj : (__throw_bad_optional_access("Attempt to access value of a " 749*38fd1498Szrj "disengaged optional object"), 750*38fd1498Szrj this->_M_get()); 751*38fd1498Szrj } 752*38fd1498Szrj 753*38fd1498Szrj constexpr _Tp& 754*38fd1498Szrj value()& 755*38fd1498Szrj { 756*38fd1498Szrj return this->_M_is_engaged() 757*38fd1498Szrj ? this->_M_get() 758*38fd1498Szrj : (__throw_bad_optional_access("Attempt to access value of a " 759*38fd1498Szrj "disengaged optional object"), 760*38fd1498Szrj this->_M_get()); 761*38fd1498Szrj } 762*38fd1498Szrj 763*38fd1498Szrj constexpr _Tp&& 764*38fd1498Szrj value()&& 765*38fd1498Szrj { 766*38fd1498Szrj return this->_M_is_engaged() 767*38fd1498Szrj ? std::move(this->_M_get()) 768*38fd1498Szrj : (__throw_bad_optional_access("Attempt to access value of a " 769*38fd1498Szrj "disengaged optional object"), 770*38fd1498Szrj std::move(this->_M_get())); 771*38fd1498Szrj } 772*38fd1498Szrj 773*38fd1498Szrj constexpr const _Tp&& 774*38fd1498Szrj value() const&& 775*38fd1498Szrj { 776*38fd1498Szrj return this->_M_is_engaged() 777*38fd1498Szrj ? std::move(this->_M_get()) 778*38fd1498Szrj : (__throw_bad_optional_access("Attempt to access value of a " 779*38fd1498Szrj "disengaged optional object"), 780*38fd1498Szrj std::move(this->_M_get())); 781*38fd1498Szrj } 782*38fd1498Szrj 783*38fd1498Szrj template<typename _Up> 784*38fd1498Szrj constexpr _Tp 785*38fd1498Szrj value_or(_Up&& __u) const& 786*38fd1498Szrj { 787*38fd1498Szrj static_assert(__and_<is_copy_constructible<_Tp>, 788*38fd1498Szrj is_convertible<_Up&&, _Tp>>(), 789*38fd1498Szrj "Cannot return value"); 790*38fd1498Szrj 791*38fd1498Szrj return this->_M_is_engaged() 792*38fd1498Szrj ? this->_M_get() 793*38fd1498Szrj : static_cast<_Tp>(std::forward<_Up>(__u)); 794*38fd1498Szrj } 795*38fd1498Szrj 796*38fd1498Szrj template<typename _Up> 797*38fd1498Szrj _Tp 798*38fd1498Szrj value_or(_Up&& __u) && 799*38fd1498Szrj { 800*38fd1498Szrj static_assert(__and_<is_move_constructible<_Tp>, 801*38fd1498Szrj is_convertible<_Up&&, _Tp>>(), 802*38fd1498Szrj "Cannot return value" ); 803*38fd1498Szrj 804*38fd1498Szrj return this->_M_is_engaged() 805*38fd1498Szrj ? std::move(this->_M_get()) 806*38fd1498Szrj : static_cast<_Tp>(std::forward<_Up>(__u)); 807*38fd1498Szrj } 808*38fd1498Szrj }; 809*38fd1498Szrj 810*38fd1498Szrj // [X.Y.8] Comparisons between optional values. 811*38fd1498Szrj template<typename _Tp> 812*38fd1498Szrj constexpr bool 813*38fd1498Szrj operator==(const optional<_Tp>& __lhs, const optional<_Tp>& __rhs) 814*38fd1498Szrj { 815*38fd1498Szrj return static_cast<bool>(__lhs) == static_cast<bool>(__rhs) 816*38fd1498Szrj && (!__lhs || *__lhs == *__rhs); 817*38fd1498Szrj } 818*38fd1498Szrj 819*38fd1498Szrj template<typename _Tp> 820*38fd1498Szrj constexpr bool 821*38fd1498Szrj operator!=(const optional<_Tp>& __lhs, const optional<_Tp>& __rhs) 822*38fd1498Szrj { return !(__lhs == __rhs); } 823*38fd1498Szrj 824*38fd1498Szrj template<typename _Tp> 825*38fd1498Szrj constexpr bool 826*38fd1498Szrj operator<(const optional<_Tp>& __lhs, const optional<_Tp>& __rhs) 827*38fd1498Szrj { 828*38fd1498Szrj return static_cast<bool>(__rhs) && (!__lhs || *__lhs < *__rhs); 829*38fd1498Szrj } 830*38fd1498Szrj 831*38fd1498Szrj template<typename _Tp> 832*38fd1498Szrj constexpr bool 833*38fd1498Szrj operator>(const optional<_Tp>& __lhs, const optional<_Tp>& __rhs) 834*38fd1498Szrj { return __rhs < __lhs; } 835*38fd1498Szrj 836*38fd1498Szrj template<typename _Tp> 837*38fd1498Szrj constexpr bool 838*38fd1498Szrj operator<=(const optional<_Tp>& __lhs, const optional<_Tp>& __rhs) 839*38fd1498Szrj { return !(__rhs < __lhs); } 840*38fd1498Szrj 841*38fd1498Szrj template<typename _Tp> 842*38fd1498Szrj constexpr bool 843*38fd1498Szrj operator>=(const optional<_Tp>& __lhs, const optional<_Tp>& __rhs) 844*38fd1498Szrj { return !(__lhs < __rhs); } 845*38fd1498Szrj 846*38fd1498Szrj // [X.Y.9] Comparisons with nullopt. 847*38fd1498Szrj template<typename _Tp> 848*38fd1498Szrj constexpr bool 849*38fd1498Szrj operator==(const optional<_Tp>& __lhs, nullopt_t) noexcept 850*38fd1498Szrj { return !__lhs; } 851*38fd1498Szrj 852*38fd1498Szrj template<typename _Tp> 853*38fd1498Szrj constexpr bool 854*38fd1498Szrj operator==(nullopt_t, const optional<_Tp>& __rhs) noexcept 855*38fd1498Szrj { return !__rhs; } 856*38fd1498Szrj 857*38fd1498Szrj template<typename _Tp> 858*38fd1498Szrj constexpr bool 859*38fd1498Szrj operator!=(const optional<_Tp>& __lhs, nullopt_t) noexcept 860*38fd1498Szrj { return static_cast<bool>(__lhs); } 861*38fd1498Szrj 862*38fd1498Szrj template<typename _Tp> 863*38fd1498Szrj constexpr bool 864*38fd1498Szrj operator!=(nullopt_t, const optional<_Tp>& __rhs) noexcept 865*38fd1498Szrj { return static_cast<bool>(__rhs); } 866*38fd1498Szrj 867*38fd1498Szrj template<typename _Tp> 868*38fd1498Szrj constexpr bool 869*38fd1498Szrj operator<(const optional<_Tp>& /* __lhs */, nullopt_t) noexcept 870*38fd1498Szrj { return false; } 871*38fd1498Szrj 872*38fd1498Szrj template<typename _Tp> 873*38fd1498Szrj constexpr bool 874*38fd1498Szrj operator<(nullopt_t, const optional<_Tp>& __rhs) noexcept 875*38fd1498Szrj { return static_cast<bool>(__rhs); } 876*38fd1498Szrj 877*38fd1498Szrj template<typename _Tp> 878*38fd1498Szrj constexpr bool 879*38fd1498Szrj operator>(const optional<_Tp>& __lhs, nullopt_t) noexcept 880*38fd1498Szrj { return static_cast<bool>(__lhs); } 881*38fd1498Szrj 882*38fd1498Szrj template<typename _Tp> 883*38fd1498Szrj constexpr bool 884*38fd1498Szrj operator>(nullopt_t, const optional<_Tp>& /* __rhs */) noexcept 885*38fd1498Szrj { return false; } 886*38fd1498Szrj 887*38fd1498Szrj template<typename _Tp> 888*38fd1498Szrj constexpr bool 889*38fd1498Szrj operator<=(const optional<_Tp>& __lhs, nullopt_t) noexcept 890*38fd1498Szrj { return !__lhs; } 891*38fd1498Szrj 892*38fd1498Szrj template<typename _Tp> 893*38fd1498Szrj constexpr bool 894*38fd1498Szrj operator<=(nullopt_t, const optional<_Tp>& /* __rhs */) noexcept 895*38fd1498Szrj { return true; } 896*38fd1498Szrj 897*38fd1498Szrj template<typename _Tp> 898*38fd1498Szrj constexpr bool 899*38fd1498Szrj operator>=(const optional<_Tp>& /* __lhs */, nullopt_t) noexcept 900*38fd1498Szrj { return true; } 901*38fd1498Szrj 902*38fd1498Szrj template<typename _Tp> 903*38fd1498Szrj constexpr bool 904*38fd1498Szrj operator>=(nullopt_t, const optional<_Tp>& __rhs) noexcept 905*38fd1498Szrj { return !__rhs; } 906*38fd1498Szrj 907*38fd1498Szrj // [X.Y.10] Comparisons with value type. 908*38fd1498Szrj template<typename _Tp> 909*38fd1498Szrj constexpr bool 910*38fd1498Szrj operator==(const optional<_Tp>& __lhs, const _Tp& __rhs) 911*38fd1498Szrj { return __lhs && *__lhs == __rhs; } 912*38fd1498Szrj 913*38fd1498Szrj template<typename _Tp> 914*38fd1498Szrj constexpr bool 915*38fd1498Szrj operator==(const _Tp& __lhs, const optional<_Tp>& __rhs) 916*38fd1498Szrj { return __rhs && __lhs == *__rhs; } 917*38fd1498Szrj 918*38fd1498Szrj template<typename _Tp> 919*38fd1498Szrj constexpr bool 920*38fd1498Szrj operator!=(const optional<_Tp>& __lhs, _Tp const& __rhs) 921*38fd1498Szrj { return !__lhs || !(*__lhs == __rhs); } 922*38fd1498Szrj 923*38fd1498Szrj template<typename _Tp> 924*38fd1498Szrj constexpr bool 925*38fd1498Szrj operator!=(const _Tp& __lhs, const optional<_Tp>& __rhs) 926*38fd1498Szrj { return !__rhs || !(__lhs == *__rhs); } 927*38fd1498Szrj 928*38fd1498Szrj template<typename _Tp> 929*38fd1498Szrj constexpr bool 930*38fd1498Szrj operator<(const optional<_Tp>& __lhs, const _Tp& __rhs) 931*38fd1498Szrj { return !__lhs || *__lhs < __rhs; } 932*38fd1498Szrj 933*38fd1498Szrj template<typename _Tp> 934*38fd1498Szrj constexpr bool 935*38fd1498Szrj operator<(const _Tp& __lhs, const optional<_Tp>& __rhs) 936*38fd1498Szrj { return __rhs && __lhs < *__rhs; } 937*38fd1498Szrj 938*38fd1498Szrj template<typename _Tp> 939*38fd1498Szrj constexpr bool 940*38fd1498Szrj operator>(const optional<_Tp>& __lhs, const _Tp& __rhs) 941*38fd1498Szrj { return __lhs && __rhs < *__lhs; } 942*38fd1498Szrj 943*38fd1498Szrj template<typename _Tp> 944*38fd1498Szrj constexpr bool 945*38fd1498Szrj operator>(const _Tp& __lhs, const optional<_Tp>& __rhs) 946*38fd1498Szrj { return !__rhs || *__rhs < __lhs; } 947*38fd1498Szrj 948*38fd1498Szrj template<typename _Tp> 949*38fd1498Szrj constexpr bool 950*38fd1498Szrj operator<=(const optional<_Tp>& __lhs, const _Tp& __rhs) 951*38fd1498Szrj { return !__lhs || !(__rhs < *__lhs); } 952*38fd1498Szrj 953*38fd1498Szrj template<typename _Tp> 954*38fd1498Szrj constexpr bool 955*38fd1498Szrj operator<=(const _Tp& __lhs, const optional<_Tp>& __rhs) 956*38fd1498Szrj { return __rhs && !(*__rhs < __lhs); } 957*38fd1498Szrj 958*38fd1498Szrj template<typename _Tp> 959*38fd1498Szrj constexpr bool 960*38fd1498Szrj operator>=(const optional<_Tp>& __lhs, const _Tp& __rhs) 961*38fd1498Szrj { return __lhs && !(*__lhs < __rhs); } 962*38fd1498Szrj 963*38fd1498Szrj template<typename _Tp> 964*38fd1498Szrj constexpr bool 965*38fd1498Szrj operator>=(const _Tp& __lhs, const optional<_Tp>& __rhs) 966*38fd1498Szrj { return !__rhs || !(__lhs < *__rhs); } 967*38fd1498Szrj 968*38fd1498Szrj // [X.Y.11] 969*38fd1498Szrj template<typename _Tp> 970*38fd1498Szrj inline void 971*38fd1498Szrj swap(optional<_Tp>& __lhs, optional<_Tp>& __rhs) 972*38fd1498Szrj noexcept(noexcept(__lhs.swap(__rhs))) 973*38fd1498Szrj { __lhs.swap(__rhs); } 974*38fd1498Szrj 975*38fd1498Szrj template<typename _Tp> 976*38fd1498Szrj constexpr optional<decay_t<_Tp>> 977*38fd1498Szrj make_optional(_Tp&& __t) 978*38fd1498Szrj { return optional<decay_t<_Tp>> { std::forward<_Tp>(__t) }; } 979*38fd1498Szrj 980*38fd1498Szrj // @} group optional 981*38fd1498Szrj} // namespace fundamentals_v1 982*38fd1498Szrj} // namespace experimental 983*38fd1498Szrj 984*38fd1498Szrj // [X.Y.12] 985*38fd1498Szrj template<typename _Tp> 986*38fd1498Szrj struct hash<experimental::optional<_Tp>> 987*38fd1498Szrj { 988*38fd1498Szrj using result_type = size_t; 989*38fd1498Szrj using argument_type = experimental::optional<_Tp>; 990*38fd1498Szrj 991*38fd1498Szrj size_t 992*38fd1498Szrj operator()(const experimental::optional<_Tp>& __t) const 993*38fd1498Szrj noexcept(noexcept(hash<_Tp> {}(*__t))) 994*38fd1498Szrj { 995*38fd1498Szrj // We pick an arbitrary hash for disengaged optionals which hopefully 996*38fd1498Szrj // usual values of _Tp won't typically hash to. 997*38fd1498Szrj constexpr size_t __magic_disengaged_hash = static_cast<size_t>(-3333); 998*38fd1498Szrj return __t ? hash<_Tp> {}(*__t) : __magic_disengaged_hash; 999*38fd1498Szrj } 1000*38fd1498Szrj }; 1001*38fd1498Szrj 1002*38fd1498Szrj_GLIBCXX_END_NAMESPACE_VERSION 1003*38fd1498Szrj} // namespace std 1004*38fd1498Szrj 1005*38fd1498Szrj#endif // C++14 1006*38fd1498Szrj 1007*38fd1498Szrj#endif // _GLIBCXX_EXPERIMENTAL_OPTIONAL 1008