138fd1498Szrj// <optional> -*- C++ -*- 238fd1498Szrj 338fd1498Szrj// Copyright (C) 2013-2018 Free Software Foundation, Inc. 438fd1498Szrj// 538fd1498Szrj// This file is part of the GNU ISO C++ Library. This library is free 638fd1498Szrj// software; you can redistribute it and/or modify it under the 738fd1498Szrj// terms of the GNU General Public License as published by the 838fd1498Szrj// Free Software Foundation; either version 3, or (at your option) 938fd1498Szrj// any later version. 1038fd1498Szrj 1138fd1498Szrj// This library is distributed in the hope that it will be useful, 1238fd1498Szrj// but WITHOUT ANY WARRANTY; without even the implied warranty of 1338fd1498Szrj// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1438fd1498Szrj// GNU General Public License for more details. 1538fd1498Szrj 1638fd1498Szrj// Under Section 7 of GPL version 3, you are granted additional 1738fd1498Szrj// permissions described in the GCC Runtime Library Exception, version 1838fd1498Szrj// 3.1, as published by the Free Software Foundation. 1938fd1498Szrj 2038fd1498Szrj// You should have received a copy of the GNU General Public License and 2138fd1498Szrj// a copy of the GCC Runtime Library Exception along with this program; 2238fd1498Szrj// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see 2338fd1498Szrj// <http://www.gnu.org/licenses/>. 2438fd1498Szrj 2538fd1498Szrj/** @file include/optional 2638fd1498Szrj * This is a Standard C++ Library header. 2738fd1498Szrj */ 2838fd1498Szrj 2938fd1498Szrj#ifndef _GLIBCXX_OPTIONAL 3038fd1498Szrj#define _GLIBCXX_OPTIONAL 1 3138fd1498Szrj 3238fd1498Szrj#pragma GCC system_header 3338fd1498Szrj 3438fd1498Szrj#if __cplusplus >= 201703L 3538fd1498Szrj 3638fd1498Szrj#include <utility> 3738fd1498Szrj#include <type_traits> 3838fd1498Szrj#include <stdexcept> 3938fd1498Szrj#include <new> 4038fd1498Szrj#include <initializer_list> 4138fd1498Szrj#include <bits/functexcept.h> 4238fd1498Szrj#include <bits/functional_hash.h> 4338fd1498Szrj#include <bits/enable_special_members.h> 4438fd1498Szrj 4538fd1498Szrjnamespace std _GLIBCXX_VISIBILITY(default) 4638fd1498Szrj{ 4738fd1498Szrj_GLIBCXX_BEGIN_NAMESPACE_VERSION 4838fd1498Szrj 4938fd1498Szrj /** 5038fd1498Szrj * @addtogroup utilities 5138fd1498Szrj * @{ 5238fd1498Szrj */ 5338fd1498Szrj 5438fd1498Szrj#define __cpp_lib_optional 201603 5538fd1498Szrj 5638fd1498Szrj template<typename _Tp> 5738fd1498Szrj class optional; 5838fd1498Szrj 5938fd1498Szrj /// Tag type to disengage optional objects. 6038fd1498Szrj struct nullopt_t 6138fd1498Szrj { 6238fd1498Szrj // Do not user-declare default constructor at all for 6338fd1498Szrj // optional_value = {} syntax to work. 6438fd1498Szrj // nullopt_t() = delete; 6538fd1498Szrj 6638fd1498Szrj // Used for constructing nullopt. 6738fd1498Szrj enum class _Construct { _Token }; 6838fd1498Szrj 6938fd1498Szrj // Must be constexpr for nullopt_t to be literal. 7038fd1498Szrj explicit constexpr nullopt_t(_Construct) { } 7138fd1498Szrj }; 7238fd1498Szrj 7338fd1498Szrj /// Tag to disengage optional objects. 7438fd1498Szrj inline constexpr nullopt_t nullopt { nullopt_t::_Construct::_Token }; 7538fd1498Szrj 7638fd1498Szrj /** 7738fd1498Szrj * @brief Exception class thrown when a disengaged optional object is 7838fd1498Szrj * dereferenced. 7938fd1498Szrj * @ingroup exceptions 8038fd1498Szrj */ 8138fd1498Szrj class bad_optional_access : public exception 8238fd1498Szrj { 8338fd1498Szrj public: 8438fd1498Szrj bad_optional_access() { } 85*58e805e6Szrj 8638fd1498Szrj virtual const char* what() const noexcept override 8738fd1498Szrj { return "bad optional access"; } 8838fd1498Szrj 8938fd1498Szrj virtual ~bad_optional_access() noexcept = default; 9038fd1498Szrj }; 9138fd1498Szrj 9238fd1498Szrj void 9338fd1498Szrj __throw_bad_optional_access() 9438fd1498Szrj __attribute__((__noreturn__)); 9538fd1498Szrj 9638fd1498Szrj // XXX Does not belong here. 9738fd1498Szrj inline void 9838fd1498Szrj __throw_bad_optional_access() 9938fd1498Szrj { _GLIBCXX_THROW_OR_ABORT(bad_optional_access()); } 10038fd1498Szrj 10138fd1498Szrj 10238fd1498Szrj // Payload for optionals with non-trivial destructor. 10338fd1498Szrj template <typename _Tp, 10438fd1498Szrj bool /*_HasTrivialDestructor*/ = 105*58e805e6Szrj is_trivially_destructible_v<_Tp>, 106*58e805e6Szrj bool /*_HasTrivialCopy */ = 107*58e805e6Szrj is_trivially_copy_assignable_v<_Tp> 108*58e805e6Szrj && is_trivially_copy_constructible_v<_Tp>, 109*58e805e6Szrj bool /*_HasTrivialMove */ = 110*58e805e6Szrj is_trivially_move_assignable_v<_Tp> 111*58e805e6Szrj && is_trivially_move_constructible_v<_Tp>> 11238fd1498Szrj struct _Optional_payload 11338fd1498Szrj { 114*58e805e6Szrj constexpr _Optional_payload() noexcept : _M_empty() { } 11538fd1498Szrj 11638fd1498Szrj template <typename... _Args> 117*58e805e6Szrj constexpr 118*58e805e6Szrj _Optional_payload(in_place_t, _Args&&... __args) 119*58e805e6Szrj : _M_payload(std::forward<_Args>(__args)...), _M_engaged(true) { } 12038fd1498Szrj 12138fd1498Szrj template<typename _Up, typename... _Args> 122*58e805e6Szrj constexpr 123*58e805e6Szrj _Optional_payload(std::initializer_list<_Up> __il, 12438fd1498Szrj _Args&&... __args) 12538fd1498Szrj : _M_payload(__il, std::forward<_Args>(__args)...), 126*58e805e6Szrj _M_engaged(true) 127*58e805e6Szrj { } 128*58e805e6Szrj 12938fd1498Szrj constexpr 13038fd1498Szrj _Optional_payload(bool __engaged, const _Optional_payload& __other) 13138fd1498Szrj : _Optional_payload(__other) 13238fd1498Szrj { } 13338fd1498Szrj 13438fd1498Szrj constexpr 13538fd1498Szrj _Optional_payload(bool __engaged, _Optional_payload&& __other) 13638fd1498Szrj : _Optional_payload(std::move(__other)) 13738fd1498Szrj { } 13838fd1498Szrj 139*58e805e6Szrj constexpr 140*58e805e6Szrj _Optional_payload(const _Optional_payload& __other) 14138fd1498Szrj { 14238fd1498Szrj if (__other._M_engaged) 14338fd1498Szrj this->_M_construct(__other._M_payload); 14438fd1498Szrj } 14538fd1498Szrj 146*58e805e6Szrj constexpr 147*58e805e6Szrj _Optional_payload(_Optional_payload&& __other) 14838fd1498Szrj { 14938fd1498Szrj if (__other._M_engaged) 15038fd1498Szrj this->_M_construct(std::move(__other._M_payload)); 15138fd1498Szrj } 15238fd1498Szrj 153*58e805e6Szrj constexpr 15438fd1498Szrj _Optional_payload& 15538fd1498Szrj operator=(const _Optional_payload& __other) 15638fd1498Szrj { 15738fd1498Szrj if (this->_M_engaged && __other._M_engaged) 15838fd1498Szrj this->_M_get() = __other._M_get(); 15938fd1498Szrj else 16038fd1498Szrj { 16138fd1498Szrj if (__other._M_engaged) 16238fd1498Szrj this->_M_construct(__other._M_get()); 16338fd1498Szrj else 16438fd1498Szrj this->_M_reset(); 16538fd1498Szrj } 16638fd1498Szrj return *this; 16738fd1498Szrj } 16838fd1498Szrj 169*58e805e6Szrj constexpr 17038fd1498Szrj _Optional_payload& 17138fd1498Szrj operator=(_Optional_payload&& __other) 17238fd1498Szrj noexcept(__and_<is_nothrow_move_constructible<_Tp>, 17338fd1498Szrj is_nothrow_move_assignable<_Tp>>()) 17438fd1498Szrj { 17538fd1498Szrj if (this->_M_engaged && __other._M_engaged) 17638fd1498Szrj this->_M_get() = std::move(__other._M_get()); 17738fd1498Szrj else 17838fd1498Szrj { 17938fd1498Szrj if (__other._M_engaged) 18038fd1498Szrj this->_M_construct(std::move(__other._M_get())); 18138fd1498Szrj else 18238fd1498Szrj this->_M_reset(); 18338fd1498Szrj } 18438fd1498Szrj return *this; 18538fd1498Szrj } 18638fd1498Szrj 18738fd1498Szrj using _Stored_type = remove_const_t<_Tp>; 188*58e805e6Szrj 18938fd1498Szrj struct _Empty_byte { }; 190*58e805e6Szrj 19138fd1498Szrj union { 19238fd1498Szrj _Empty_byte _M_empty; 19338fd1498Szrj _Stored_type _M_payload; 19438fd1498Szrj }; 19538fd1498Szrj bool _M_engaged = false; 19638fd1498Szrj 19738fd1498Szrj ~_Optional_payload() 19838fd1498Szrj { 19938fd1498Szrj if (_M_engaged) 20038fd1498Szrj _M_payload.~_Stored_type(); 20138fd1498Szrj } 20238fd1498Szrj 20338fd1498Szrj template<typename... _Args> 20438fd1498Szrj void 20538fd1498Szrj _M_construct(_Args&&... __args) 20638fd1498Szrj noexcept(is_nothrow_constructible<_Stored_type, _Args...>()) 20738fd1498Szrj { 20838fd1498Szrj ::new ((void *) std::__addressof(this->_M_payload)) 20938fd1498Szrj _Stored_type(std::forward<_Args>(__args)...); 21038fd1498Szrj this->_M_engaged = true; 21138fd1498Szrj } 21238fd1498Szrj 21338fd1498Szrj // The _M_get operations have _M_engaged as a precondition. 21438fd1498Szrj constexpr _Tp& 21538fd1498Szrj _M_get() noexcept 216*58e805e6Szrj { return this->_M_payload; } 21738fd1498Szrj 21838fd1498Szrj constexpr const _Tp& 21938fd1498Szrj _M_get() const noexcept 220*58e805e6Szrj { return this->_M_payload; } 22138fd1498Szrj 22238fd1498Szrj // _M_reset is a 'safe' operation with no precondition. 223*58e805e6Szrj constexpr 22438fd1498Szrj void 22538fd1498Szrj _M_reset() noexcept 22638fd1498Szrj { 22738fd1498Szrj if (this->_M_engaged) 22838fd1498Szrj { 22938fd1498Szrj this->_M_engaged = false; 23038fd1498Szrj this->_M_payload.~_Stored_type(); 23138fd1498Szrj } 23238fd1498Szrj } 23338fd1498Szrj }; 23438fd1498Szrj 235*58e805e6Szrj // Payload for potentially-constexpr optionals. 23638fd1498Szrj template <typename _Tp> 23738fd1498Szrj struct _Optional_payload<_Tp, true, true, true> 23838fd1498Szrj { 239*58e805e6Szrj constexpr _Optional_payload() noexcept 24038fd1498Szrj : _M_empty(), _M_engaged(false) { } 24138fd1498Szrj 24238fd1498Szrj template<typename... _Args> 243*58e805e6Szrj constexpr 244*58e805e6Szrj _Optional_payload(in_place_t, _Args&&... __args) 245*58e805e6Szrj : _M_payload(std::forward<_Args>(__args)...), _M_engaged(true) 24638fd1498Szrj { } 24738fd1498Szrj 24838fd1498Szrj template<typename _Up, typename... _Args> 249*58e805e6Szrj constexpr 250*58e805e6Szrj _Optional_payload(std::initializer_list<_Up> __il, 25138fd1498Szrj _Args&&... __args) 25238fd1498Szrj : _M_payload(__il, std::forward<_Args>(__args)...), 25338fd1498Szrj _M_engaged(true) 25438fd1498Szrj { } 25538fd1498Szrj 256*58e805e6Szrj constexpr 257*58e805e6Szrj _Optional_payload(bool __engaged, const _Optional_payload& __other) 258*58e805e6Szrj : _M_engaged(__engaged) 259*58e805e6Szrj { 260*58e805e6Szrj if (__engaged) 261*58e805e6Szrj _M_construct(__other._M_get()); 262*58e805e6Szrj } 26338fd1498Szrj 264*58e805e6Szrj constexpr 265*58e805e6Szrj _Optional_payload(bool __engaged, _Optional_payload&& __other) 266*58e805e6Szrj : _M_engaged(__engaged) 267*58e805e6Szrj { 268*58e805e6Szrj if (__engaged) 269*58e805e6Szrj _M_construct(std::move(__other._M_get())); 270*58e805e6Szrj } 27138fd1498Szrj 27238fd1498Szrj using _Stored_type = remove_const_t<_Tp>; 273*58e805e6Szrj 27438fd1498Szrj struct _Empty_byte { }; 275*58e805e6Szrj 27638fd1498Szrj union { 27738fd1498Szrj _Empty_byte _M_empty; 27838fd1498Szrj _Stored_type _M_payload; 27938fd1498Szrj }; 28038fd1498Szrj bool _M_engaged; 281*58e805e6Szrj 282*58e805e6Szrj // The _M_get operations have _M_engaged as a precondition. 283*58e805e6Szrj constexpr _Tp& 284*58e805e6Szrj _M_get() noexcept 285*58e805e6Szrj { return this->_M_payload; } 286*58e805e6Szrj 287*58e805e6Szrj constexpr const _Tp& 288*58e805e6Szrj _M_get() const noexcept 289*58e805e6Szrj { return this->_M_payload; } 29038fd1498Szrj }; 29138fd1498Szrj 29238fd1498Szrj // Payload for optionals with non-trivial copy assignment. 29338fd1498Szrj template <typename _Tp> 29438fd1498Szrj struct _Optional_payload<_Tp, true, false, true> 29538fd1498Szrj { 296*58e805e6Szrj constexpr _Optional_payload() noexcept 29738fd1498Szrj : _M_empty(), _M_engaged(false) { } 29838fd1498Szrj 29938fd1498Szrj template<typename... _Args> 300*58e805e6Szrj constexpr 301*58e805e6Szrj _Optional_payload(in_place_t, _Args&&... __args) 302*58e805e6Szrj : _M_payload(std::forward<_Args>(__args)...), _M_engaged(true) 30338fd1498Szrj { } 30438fd1498Szrj 30538fd1498Szrj template<typename _Up, typename... _Args> 306*58e805e6Szrj constexpr 307*58e805e6Szrj _Optional_payload(std::initializer_list<_Up> __il, 30838fd1498Szrj _Args&&... __args) 30938fd1498Szrj : _M_payload(__il, std::forward<_Args>(__args)...), 31038fd1498Szrj _M_engaged(true) 31138fd1498Szrj { } 31238fd1498Szrj 313*58e805e6Szrj constexpr 314*58e805e6Szrj _Optional_payload(bool __engaged, const _Optional_payload& __other) 315*58e805e6Szrj : _M_engaged(__engaged) 316*58e805e6Szrj { 317*58e805e6Szrj if (__engaged) 318*58e805e6Szrj _M_construct(__other._M_get()); 319*58e805e6Szrj } 32038fd1498Szrj 321*58e805e6Szrj constexpr 322*58e805e6Szrj _Optional_payload(bool __engaged, _Optional_payload&& __other) 323*58e805e6Szrj : _M_engaged(__engaged) 324*58e805e6Szrj { 325*58e805e6Szrj if (__engaged) 326*58e805e6Szrj _M_construct(std::move(__other._M_get())); 327*58e805e6Szrj } 32838fd1498Szrj 32938fd1498Szrj _Optional_payload(const _Optional_payload&) = default; 33038fd1498Szrj _Optional_payload(_Optional_payload&&) = default; 33138fd1498Szrj 332*58e805e6Szrj constexpr 33338fd1498Szrj _Optional_payload& 33438fd1498Szrj operator=(const _Optional_payload& __other) 33538fd1498Szrj { 33638fd1498Szrj if (this->_M_engaged && __other._M_engaged) 33738fd1498Szrj this->_M_get() = __other._M_get(); 33838fd1498Szrj else 33938fd1498Szrj { 34038fd1498Szrj if (__other._M_engaged) 34138fd1498Szrj this->_M_construct(__other._M_get()); 34238fd1498Szrj else 34338fd1498Szrj this->_M_reset(); 34438fd1498Szrj } 34538fd1498Szrj return *this; 34638fd1498Szrj } 34738fd1498Szrj 34838fd1498Szrj _Optional_payload& 34938fd1498Szrj operator=(_Optional_payload&& __other) = default; 35038fd1498Szrj 35138fd1498Szrj using _Stored_type = remove_const_t<_Tp>; 352*58e805e6Szrj 35338fd1498Szrj struct _Empty_byte { }; 354*58e805e6Szrj 35538fd1498Szrj union { 35638fd1498Szrj _Empty_byte _M_empty; 35738fd1498Szrj _Stored_type _M_payload; 35838fd1498Szrj }; 35938fd1498Szrj bool _M_engaged; 36038fd1498Szrj 36138fd1498Szrj template<typename... _Args> 36238fd1498Szrj void 36338fd1498Szrj _M_construct(_Args&&... __args) 36438fd1498Szrj noexcept(is_nothrow_constructible<_Stored_type, _Args...>()) 36538fd1498Szrj { 36638fd1498Szrj ::new ((void *) std::__addressof(this->_M_payload)) 36738fd1498Szrj _Stored_type(std::forward<_Args>(__args)...); 36838fd1498Szrj this->_M_engaged = true; 36938fd1498Szrj } 37038fd1498Szrj 37138fd1498Szrj // The _M_get operations have _M_engaged as a precondition. 37238fd1498Szrj constexpr _Tp& 37338fd1498Szrj _M_get() noexcept 374*58e805e6Szrj { return this->_M_payload; } 37538fd1498Szrj 37638fd1498Szrj constexpr const _Tp& 37738fd1498Szrj _M_get() const noexcept 378*58e805e6Szrj { return this->_M_payload; } 37938fd1498Szrj 38038fd1498Szrj // _M_reset is a 'safe' operation with no precondition. 381*58e805e6Szrj constexpr 38238fd1498Szrj void 38338fd1498Szrj _M_reset() noexcept 38438fd1498Szrj { 38538fd1498Szrj if (this->_M_engaged) 38638fd1498Szrj { 38738fd1498Szrj this->_M_engaged = false; 38838fd1498Szrj this->_M_payload.~_Stored_type(); 38938fd1498Szrj } 39038fd1498Szrj } 39138fd1498Szrj }; 39238fd1498Szrj 39338fd1498Szrj // Payload for optionals with non-trivial move assignment. 39438fd1498Szrj template <typename _Tp> 39538fd1498Szrj struct _Optional_payload<_Tp, true, true, false> 39638fd1498Szrj { 397*58e805e6Szrj constexpr _Optional_payload() noexcept 39838fd1498Szrj : _M_empty(), _M_engaged(false) { } 39938fd1498Szrj 40038fd1498Szrj template<typename... _Args> 401*58e805e6Szrj constexpr 402*58e805e6Szrj _Optional_payload(in_place_t, _Args&&... __args) 40338fd1498Szrj : _M_payload(std::forward<_Args>(__args)...), 40438fd1498Szrj _M_engaged(true) 40538fd1498Szrj { } 40638fd1498Szrj 40738fd1498Szrj template<typename _Up, typename... _Args> 408*58e805e6Szrj constexpr 409*58e805e6Szrj _Optional_payload(std::initializer_list<_Up> __il, 41038fd1498Szrj _Args&&... __args) 41138fd1498Szrj : _M_payload(__il, std::forward<_Args>(__args)...), 41238fd1498Szrj _M_engaged(true) 41338fd1498Szrj { } 41438fd1498Szrj 415*58e805e6Szrj constexpr 416*58e805e6Szrj _Optional_payload(bool __engaged, const _Optional_payload& __other) 417*58e805e6Szrj : _M_engaged(__engaged) 418*58e805e6Szrj { 419*58e805e6Szrj if (__engaged) 420*58e805e6Szrj _M_construct(__other._M_get()); 421*58e805e6Szrj } 42238fd1498Szrj 423*58e805e6Szrj constexpr 424*58e805e6Szrj _Optional_payload(bool __engaged, _Optional_payload&& __other) 425*58e805e6Szrj : _M_engaged(__engaged) 426*58e805e6Szrj { 427*58e805e6Szrj if (__engaged) 428*58e805e6Szrj _M_construct(std::move(__other._M_get())); 429*58e805e6Szrj } 43038fd1498Szrj 43138fd1498Szrj _Optional_payload(const _Optional_payload&) = default; 43238fd1498Szrj _Optional_payload(_Optional_payload&&) = default; 43338fd1498Szrj 43438fd1498Szrj _Optional_payload& 43538fd1498Szrj operator=(const _Optional_payload& __other) = default; 43638fd1498Szrj 437*58e805e6Szrj constexpr 43838fd1498Szrj _Optional_payload& 43938fd1498Szrj operator=(_Optional_payload&& __other) 44038fd1498Szrj noexcept(__and_<is_nothrow_move_constructible<_Tp>, 44138fd1498Szrj is_nothrow_move_assignable<_Tp>>()) 44238fd1498Szrj { 44338fd1498Szrj if (this->_M_engaged && __other._M_engaged) 44438fd1498Szrj this->_M_get() = std::move(__other._M_get()); 44538fd1498Szrj else 44638fd1498Szrj { 44738fd1498Szrj if (__other._M_engaged) 44838fd1498Szrj this->_M_construct(std::move(__other._M_get())); 44938fd1498Szrj else 45038fd1498Szrj this->_M_reset(); 45138fd1498Szrj } 45238fd1498Szrj return *this; 45338fd1498Szrj } 45438fd1498Szrj 45538fd1498Szrj using _Stored_type = remove_const_t<_Tp>; 456*58e805e6Szrj 45738fd1498Szrj struct _Empty_byte { }; 458*58e805e6Szrj 45938fd1498Szrj union { 46038fd1498Szrj _Empty_byte _M_empty; 46138fd1498Szrj _Stored_type _M_payload; 46238fd1498Szrj }; 46338fd1498Szrj bool _M_engaged; 46438fd1498Szrj 46538fd1498Szrj template<typename... _Args> 46638fd1498Szrj void 46738fd1498Szrj _M_construct(_Args&&... __args) 46838fd1498Szrj noexcept(is_nothrow_constructible<_Stored_type, _Args...>()) 46938fd1498Szrj { 47038fd1498Szrj ::new ((void *) std::__addressof(this->_M_payload)) 47138fd1498Szrj _Stored_type(std::forward<_Args>(__args)...); 47238fd1498Szrj this->_M_engaged = true; 47338fd1498Szrj } 47438fd1498Szrj 47538fd1498Szrj // The _M_get operations have _M_engaged as a precondition. 47638fd1498Szrj constexpr _Tp& 47738fd1498Szrj _M_get() noexcept 478*58e805e6Szrj { return this->_M_payload; } 47938fd1498Szrj 48038fd1498Szrj constexpr const _Tp& 48138fd1498Szrj _M_get() const noexcept 482*58e805e6Szrj { return this->_M_payload; } 48338fd1498Szrj 48438fd1498Szrj // _M_reset is a 'safe' operation with no precondition. 485*58e805e6Szrj constexpr 48638fd1498Szrj void 48738fd1498Szrj _M_reset() noexcept 48838fd1498Szrj { 48938fd1498Szrj if (this->_M_engaged) 49038fd1498Szrj { 49138fd1498Szrj this->_M_engaged = false; 49238fd1498Szrj this->_M_payload.~_Stored_type(); 49338fd1498Szrj } 49438fd1498Szrj } 49538fd1498Szrj }; 49638fd1498Szrj 49738fd1498Szrj // Payload for optionals with non-trivial copy and move assignment. 49838fd1498Szrj template <typename _Tp> 49938fd1498Szrj struct _Optional_payload<_Tp, true, false, false> 50038fd1498Szrj { 501*58e805e6Szrj constexpr _Optional_payload() noexcept 50238fd1498Szrj : _M_empty(), _M_engaged(false) {} 50338fd1498Szrj 50438fd1498Szrj template<typename... _Args> 505*58e805e6Szrj constexpr 506*58e805e6Szrj _Optional_payload(in_place_t, _Args&&... __args) 50738fd1498Szrj : _M_payload(std::forward<_Args>(__args)...), 50838fd1498Szrj _M_engaged(true) 50938fd1498Szrj { } 51038fd1498Szrj 51138fd1498Szrj template<typename _Up, typename... _Args> 512*58e805e6Szrj constexpr 513*58e805e6Szrj _Optional_payload(std::initializer_list<_Up> __il, 51438fd1498Szrj _Args&&... __args) 51538fd1498Szrj : _M_payload(__il, std::forward<_Args>(__args)...), 51638fd1498Szrj _M_engaged(true) 51738fd1498Szrj { } 51838fd1498Szrj 519*58e805e6Szrj constexpr 520*58e805e6Szrj _Optional_payload(bool __engaged, const _Optional_payload& __other) 521*58e805e6Szrj : _M_engaged(__engaged) 522*58e805e6Szrj { 523*58e805e6Szrj if (__engaged) 524*58e805e6Szrj _M_construct(__other._M_get()); 525*58e805e6Szrj } 52638fd1498Szrj 527*58e805e6Szrj constexpr 528*58e805e6Szrj _Optional_payload(bool __engaged, _Optional_payload&& __other) 529*58e805e6Szrj : _M_engaged(__engaged) 530*58e805e6Szrj { 531*58e805e6Szrj if (__engaged) 532*58e805e6Szrj _M_construct(std::move(__other._M_get())); 533*58e805e6Szrj } 53438fd1498Szrj 53538fd1498Szrj _Optional_payload(const _Optional_payload&) = default; 53638fd1498Szrj _Optional_payload(_Optional_payload&&) = default; 53738fd1498Szrj 538*58e805e6Szrj constexpr 53938fd1498Szrj _Optional_payload& 54038fd1498Szrj operator=(const _Optional_payload& __other) 54138fd1498Szrj { 54238fd1498Szrj if (this->_M_engaged && __other._M_engaged) 54338fd1498Szrj this->_M_get() = __other._M_get(); 54438fd1498Szrj else 54538fd1498Szrj { 54638fd1498Szrj if (__other._M_engaged) 54738fd1498Szrj this->_M_construct(__other._M_get()); 54838fd1498Szrj else 54938fd1498Szrj this->_M_reset(); 55038fd1498Szrj } 55138fd1498Szrj return *this; 55238fd1498Szrj } 55338fd1498Szrj 554*58e805e6Szrj constexpr 55538fd1498Szrj _Optional_payload& 55638fd1498Szrj operator=(_Optional_payload&& __other) 55738fd1498Szrj noexcept(__and_<is_nothrow_move_constructible<_Tp>, 55838fd1498Szrj is_nothrow_move_assignable<_Tp>>()) 55938fd1498Szrj { 56038fd1498Szrj if (this->_M_engaged && __other._M_engaged) 56138fd1498Szrj this->_M_get() = std::move(__other._M_get()); 56238fd1498Szrj else 56338fd1498Szrj { 56438fd1498Szrj if (__other._M_engaged) 56538fd1498Szrj this->_M_construct(std::move(__other._M_get())); 56638fd1498Szrj else 56738fd1498Szrj this->_M_reset(); 56838fd1498Szrj } 56938fd1498Szrj return *this; 57038fd1498Szrj } 57138fd1498Szrj 57238fd1498Szrj using _Stored_type = remove_const_t<_Tp>; 573*58e805e6Szrj 57438fd1498Szrj struct _Empty_byte { }; 575*58e805e6Szrj 57638fd1498Szrj union { 57738fd1498Szrj _Empty_byte _M_empty; 57838fd1498Szrj _Stored_type _M_payload; 57938fd1498Szrj }; 58038fd1498Szrj bool _M_engaged; 58138fd1498Szrj 58238fd1498Szrj template<typename... _Args> 58338fd1498Szrj void 58438fd1498Szrj _M_construct(_Args&&... __args) 58538fd1498Szrj noexcept(is_nothrow_constructible<_Stored_type, _Args...>()) 58638fd1498Szrj { 58738fd1498Szrj ::new ((void *) std::__addressof(this->_M_payload)) 58838fd1498Szrj _Stored_type(std::forward<_Args>(__args)...); 58938fd1498Szrj this->_M_engaged = true; 59038fd1498Szrj } 59138fd1498Szrj 59238fd1498Szrj // The _M_get operations have _M_engaged as a precondition. 59338fd1498Szrj constexpr _Tp& 59438fd1498Szrj _M_get() noexcept 595*58e805e6Szrj { return this->_M_payload; } 59638fd1498Szrj 59738fd1498Szrj constexpr const _Tp& 59838fd1498Szrj _M_get() const noexcept 599*58e805e6Szrj { return this->_M_payload; } 60038fd1498Szrj 60138fd1498Szrj // _M_reset is a 'safe' operation with no precondition. 602*58e805e6Szrj constexpr 60338fd1498Szrj void 60438fd1498Szrj _M_reset() noexcept 60538fd1498Szrj { 60638fd1498Szrj if (this->_M_engaged) 60738fd1498Szrj { 60838fd1498Szrj this->_M_engaged = false; 60938fd1498Szrj this->_M_payload.~_Stored_type(); 61038fd1498Szrj } 61138fd1498Szrj } 61238fd1498Szrj }; 61338fd1498Szrj 61438fd1498Szrj template<typename _Tp, typename _Dp> 61538fd1498Szrj class _Optional_base_impl 61638fd1498Szrj { 61738fd1498Szrj protected: 61838fd1498Szrj using _Stored_type = remove_const_t<_Tp>; 61938fd1498Szrj 62038fd1498Szrj // The _M_construct operation has !_M_engaged as a precondition 62138fd1498Szrj // while _M_destruct has _M_engaged as a precondition. 62238fd1498Szrj template<typename... _Args> 62338fd1498Szrj void 62438fd1498Szrj _M_construct(_Args&&... __args) 62538fd1498Szrj noexcept(is_nothrow_constructible<_Stored_type, _Args...>()) 62638fd1498Szrj { 62738fd1498Szrj ::new 62838fd1498Szrj (std::__addressof(static_cast<_Dp*>(this)->_M_payload._M_payload)) 62938fd1498Szrj _Stored_type(std::forward<_Args>(__args)...); 63038fd1498Szrj static_cast<_Dp*>(this)->_M_payload._M_engaged = true; 63138fd1498Szrj } 63238fd1498Szrj 63338fd1498Szrj void 63438fd1498Szrj _M_destruct() noexcept 63538fd1498Szrj { 63638fd1498Szrj static_cast<_Dp*>(this)->_M_payload._M_engaged = false; 63738fd1498Szrj static_cast<_Dp*>(this)->_M_payload._M_payload.~_Stored_type(); 63838fd1498Szrj } 63938fd1498Szrj 64038fd1498Szrj // _M_reset is a 'safe' operation with no precondition. 641*58e805e6Szrj constexpr 64238fd1498Szrj void 64338fd1498Szrj _M_reset() noexcept 64438fd1498Szrj { 64538fd1498Szrj if (static_cast<_Dp*>(this)->_M_payload._M_engaged) 64638fd1498Szrj static_cast<_Dp*>(this)->_M_destruct(); 64738fd1498Szrj } 64838fd1498Szrj }; 64938fd1498Szrj 65038fd1498Szrj /** 65138fd1498Szrj * @brief Class template that takes care of copy/move constructors 65238fd1498Szrj of optional 65338fd1498Szrj * 65438fd1498Szrj * Such a separate base class template is necessary in order to 65538fd1498Szrj * conditionally make copy/move constructors trivial. 65638fd1498Szrj * @see optional, _Enable_special_members 65738fd1498Szrj */ 65838fd1498Szrj template<typename _Tp, 65938fd1498Szrj bool = is_trivially_copy_constructible_v<_Tp>, 66038fd1498Szrj bool = is_trivially_move_constructible_v<_Tp>> 66138fd1498Szrj class _Optional_base 66238fd1498Szrj // protected inheritance because optional needs to reach that base too 66338fd1498Szrj : protected _Optional_base_impl<_Tp, _Optional_base<_Tp>> 66438fd1498Szrj { 66538fd1498Szrj friend class _Optional_base_impl<_Tp, _Optional_base<_Tp>>; 66638fd1498Szrj 667*58e805e6Szrj public: 66838fd1498Szrj // Constructors for disengaged optionals. 66938fd1498Szrj constexpr _Optional_base() = default; 67038fd1498Szrj 67138fd1498Szrj // Constructors for engaged optionals. 67238fd1498Szrj template<typename... _Args, 67338fd1498Szrj enable_if_t<is_constructible_v<_Tp, _Args&&...>, bool> = false> 67438fd1498Szrj constexpr explicit _Optional_base(in_place_t, _Args&&... __args) 67538fd1498Szrj : _M_payload(in_place, 67638fd1498Szrj std::forward<_Args>(__args)...) { } 67738fd1498Szrj 67838fd1498Szrj template<typename _Up, typename... _Args, 67938fd1498Szrj enable_if_t<is_constructible_v<_Tp, 68038fd1498Szrj initializer_list<_Up>&, 68138fd1498Szrj _Args&&...>, bool> = false> 68238fd1498Szrj constexpr explicit _Optional_base(in_place_t, 68338fd1498Szrj initializer_list<_Up> __il, 68438fd1498Szrj _Args&&... __args) 68538fd1498Szrj : _M_payload(in_place, 68638fd1498Szrj __il, std::forward<_Args>(__args)...) 68738fd1498Szrj { } 68838fd1498Szrj 68938fd1498Szrj // Copy and move constructors. 69038fd1498Szrj constexpr _Optional_base(const _Optional_base& __other) 69138fd1498Szrj : _M_payload(__other._M_payload._M_engaged, 69238fd1498Szrj __other._M_payload) 69338fd1498Szrj { } 69438fd1498Szrj 69538fd1498Szrj constexpr _Optional_base(_Optional_base&& __other) 69638fd1498Szrj noexcept(is_nothrow_move_constructible<_Tp>()) 69738fd1498Szrj : _M_payload(__other._M_payload._M_engaged, 69838fd1498Szrj std::move(__other._M_payload)) 69938fd1498Szrj { } 70038fd1498Szrj 70138fd1498Szrj // Assignment operators. 70238fd1498Szrj _Optional_base& operator=(const _Optional_base&) = default; 70338fd1498Szrj _Optional_base& operator=(_Optional_base&&) = default; 70438fd1498Szrj 70538fd1498Szrj protected: 70638fd1498Szrj 70738fd1498Szrj constexpr bool _M_is_engaged() const noexcept 70838fd1498Szrj { return this->_M_payload._M_engaged; } 70938fd1498Szrj 71038fd1498Szrj // The _M_get operations have _M_engaged as a precondition. 71138fd1498Szrj constexpr _Tp& 71238fd1498Szrj _M_get() noexcept 71338fd1498Szrj { 71438fd1498Szrj __glibcxx_assert(this->_M_is_engaged()); 71538fd1498Szrj return this->_M_payload._M_payload; 71638fd1498Szrj } 71738fd1498Szrj 71838fd1498Szrj constexpr const _Tp& 71938fd1498Szrj _M_get() const noexcept 72038fd1498Szrj { 72138fd1498Szrj __glibcxx_assert(this->_M_is_engaged()); 72238fd1498Szrj return this->_M_payload._M_payload; 72338fd1498Szrj } 72438fd1498Szrj 72538fd1498Szrj private: 72638fd1498Szrj _Optional_payload<_Tp> _M_payload; 72738fd1498Szrj }; 72838fd1498Szrj 72938fd1498Szrj template<typename _Tp> 73038fd1498Szrj class _Optional_base<_Tp, false, true> 73138fd1498Szrj : protected _Optional_base_impl<_Tp, _Optional_base<_Tp>> 73238fd1498Szrj { 73338fd1498Szrj friend class _Optional_base_impl<_Tp, _Optional_base<_Tp>>; 73438fd1498Szrj public: 73538fd1498Szrj 73638fd1498Szrj // Constructors for disengaged optionals. 73738fd1498Szrj constexpr _Optional_base() = default; 73838fd1498Szrj 73938fd1498Szrj // Constructors for engaged optionals. 74038fd1498Szrj template<typename... _Args, 74138fd1498Szrj enable_if_t<is_constructible_v<_Tp, _Args&&...>, bool> = false> 74238fd1498Szrj constexpr explicit _Optional_base(in_place_t, _Args&&... __args) 74338fd1498Szrj : _M_payload(in_place, 74438fd1498Szrj std::forward<_Args>(__args)...) { } 74538fd1498Szrj 74638fd1498Szrj template<typename _Up, typename... _Args, 74738fd1498Szrj enable_if_t<is_constructible_v<_Tp, 74838fd1498Szrj initializer_list<_Up>&, 74938fd1498Szrj _Args&&...>, bool> = false> 75038fd1498Szrj constexpr explicit _Optional_base(in_place_t, 75138fd1498Szrj initializer_list<_Up> __il, 75238fd1498Szrj _Args&&... __args) 75338fd1498Szrj : _M_payload(in_place, 75438fd1498Szrj __il, std::forward<_Args>(__args)...) 75538fd1498Szrj { } 75638fd1498Szrj 75738fd1498Szrj // Copy and move constructors. 75838fd1498Szrj constexpr _Optional_base(const _Optional_base& __other) 75938fd1498Szrj : _M_payload(__other._M_payload._M_engaged, 76038fd1498Szrj __other._M_payload) 76138fd1498Szrj { } 76238fd1498Szrj 76338fd1498Szrj constexpr _Optional_base(_Optional_base&& __other) = default; 76438fd1498Szrj 76538fd1498Szrj // Assignment operators. 76638fd1498Szrj _Optional_base& operator=(const _Optional_base&) = default; 76738fd1498Szrj _Optional_base& operator=(_Optional_base&&) = default; 76838fd1498Szrj 76938fd1498Szrj protected: 77038fd1498Szrj 77138fd1498Szrj constexpr bool _M_is_engaged() const noexcept 77238fd1498Szrj { return this->_M_payload._M_engaged; } 77338fd1498Szrj 77438fd1498Szrj // The _M_get operations have _M_engaged as a precondition. 77538fd1498Szrj constexpr _Tp& 77638fd1498Szrj _M_get() noexcept 77738fd1498Szrj { 77838fd1498Szrj __glibcxx_assert(this->_M_is_engaged()); 77938fd1498Szrj return this->_M_payload._M_payload; 78038fd1498Szrj } 78138fd1498Szrj 78238fd1498Szrj constexpr const _Tp& 78338fd1498Szrj _M_get() const noexcept 78438fd1498Szrj { 78538fd1498Szrj __glibcxx_assert(this->_M_is_engaged()); 78638fd1498Szrj return this->_M_payload._M_payload; 78738fd1498Szrj } 78838fd1498Szrj 78938fd1498Szrj private: 79038fd1498Szrj _Optional_payload<_Tp> _M_payload; 79138fd1498Szrj }; 79238fd1498Szrj 79338fd1498Szrj template<typename _Tp> 79438fd1498Szrj class _Optional_base<_Tp, true, false> 79538fd1498Szrj : protected _Optional_base_impl<_Tp, _Optional_base<_Tp>> 79638fd1498Szrj { 79738fd1498Szrj friend class _Optional_base_impl<_Tp, _Optional_base<_Tp>>; 79838fd1498Szrj public: 79938fd1498Szrj 80038fd1498Szrj // Constructors for disengaged optionals. 80138fd1498Szrj constexpr _Optional_base() = default; 80238fd1498Szrj 80338fd1498Szrj // Constructors for engaged optionals. 80438fd1498Szrj template<typename... _Args, 80538fd1498Szrj enable_if_t<is_constructible_v<_Tp, _Args&&...>, bool> = false> 80638fd1498Szrj constexpr explicit _Optional_base(in_place_t, _Args&&... __args) 80738fd1498Szrj : _M_payload(in_place, 80838fd1498Szrj std::forward<_Args>(__args)...) { } 80938fd1498Szrj 81038fd1498Szrj template<typename _Up, typename... _Args, 81138fd1498Szrj enable_if_t<is_constructible_v<_Tp, 81238fd1498Szrj initializer_list<_Up>&, 81338fd1498Szrj _Args&&...>, bool> = false> 81438fd1498Szrj constexpr explicit _Optional_base(in_place_t, 81538fd1498Szrj initializer_list<_Up> __il, 81638fd1498Szrj _Args&&... __args) 81738fd1498Szrj : _M_payload(in_place, 81838fd1498Szrj __il, std::forward<_Args>(__args)...) 81938fd1498Szrj { } 82038fd1498Szrj 82138fd1498Szrj // Copy and move constructors. 82238fd1498Szrj constexpr _Optional_base(const _Optional_base& __other) = default; 82338fd1498Szrj 82438fd1498Szrj constexpr _Optional_base(_Optional_base&& __other) 82538fd1498Szrj noexcept(is_nothrow_move_constructible<_Tp>()) 82638fd1498Szrj : _M_payload(__other._M_payload._M_engaged, 82738fd1498Szrj std::move(__other._M_payload)) 82838fd1498Szrj { } 82938fd1498Szrj 83038fd1498Szrj // Assignment operators. 83138fd1498Szrj _Optional_base& operator=(const _Optional_base&) = default; 83238fd1498Szrj _Optional_base& operator=(_Optional_base&&) = default; 83338fd1498Szrj 83438fd1498Szrj protected: 83538fd1498Szrj 83638fd1498Szrj constexpr bool _M_is_engaged() const noexcept 83738fd1498Szrj { return this->_M_payload._M_engaged; } 83838fd1498Szrj 83938fd1498Szrj // The _M_get operations have _M_engaged as a precondition. 84038fd1498Szrj constexpr _Tp& 84138fd1498Szrj _M_get() noexcept 84238fd1498Szrj { 84338fd1498Szrj __glibcxx_assert(this->_M_is_engaged()); 84438fd1498Szrj return this->_M_payload._M_payload; 84538fd1498Szrj } 84638fd1498Szrj 84738fd1498Szrj constexpr const _Tp& 84838fd1498Szrj _M_get() const noexcept 84938fd1498Szrj { 85038fd1498Szrj __glibcxx_assert(this->_M_is_engaged()); 85138fd1498Szrj return this->_M_payload._M_payload; 85238fd1498Szrj } 85338fd1498Szrj 85438fd1498Szrj private: 85538fd1498Szrj _Optional_payload<_Tp> _M_payload; 85638fd1498Szrj }; 85738fd1498Szrj 85838fd1498Szrj template<typename _Tp> 85938fd1498Szrj class _Optional_base<_Tp, true, true> 86038fd1498Szrj : protected _Optional_base_impl<_Tp, _Optional_base<_Tp>> 86138fd1498Szrj { 86238fd1498Szrj friend class _Optional_base_impl<_Tp, _Optional_base<_Tp>>; 86338fd1498Szrj public: 86438fd1498Szrj 86538fd1498Szrj // Constructors for disengaged optionals. 86638fd1498Szrj constexpr _Optional_base() = default; 86738fd1498Szrj 86838fd1498Szrj // Constructors for engaged optionals. 86938fd1498Szrj template<typename... _Args, 87038fd1498Szrj enable_if_t<is_constructible_v<_Tp, _Args&&...>, bool> = false> 87138fd1498Szrj constexpr explicit _Optional_base(in_place_t, _Args&&... __args) 87238fd1498Szrj : _M_payload(in_place, 87338fd1498Szrj std::forward<_Args>(__args)...) { } 87438fd1498Szrj 87538fd1498Szrj template<typename _Up, typename... _Args, 87638fd1498Szrj enable_if_t<is_constructible_v<_Tp, 87738fd1498Szrj initializer_list<_Up>&, 87838fd1498Szrj _Args&&...>, bool> = false> 87938fd1498Szrj constexpr explicit _Optional_base(in_place_t, 88038fd1498Szrj initializer_list<_Up> __il, 88138fd1498Szrj _Args&&... __args) 88238fd1498Szrj : _M_payload(in_place, 88338fd1498Szrj __il, std::forward<_Args>(__args)...) 88438fd1498Szrj { } 88538fd1498Szrj 88638fd1498Szrj // Copy and move constructors. 88738fd1498Szrj constexpr _Optional_base(const _Optional_base& __other) = default; 88838fd1498Szrj constexpr _Optional_base(_Optional_base&& __other) = default; 88938fd1498Szrj 89038fd1498Szrj // Assignment operators. 89138fd1498Szrj _Optional_base& operator=(const _Optional_base&) = default; 89238fd1498Szrj _Optional_base& operator=(_Optional_base&&) = default; 89338fd1498Szrj 89438fd1498Szrj protected: 89538fd1498Szrj 89638fd1498Szrj constexpr bool _M_is_engaged() const noexcept 89738fd1498Szrj { return this->_M_payload._M_engaged; } 89838fd1498Szrj 89938fd1498Szrj // The _M_get operations have _M_engaged as a precondition. 90038fd1498Szrj constexpr _Tp& 90138fd1498Szrj _M_get() noexcept 90238fd1498Szrj { 90338fd1498Szrj __glibcxx_assert(this->_M_is_engaged()); 90438fd1498Szrj return this->_M_payload._M_payload; 90538fd1498Szrj } 90638fd1498Szrj 90738fd1498Szrj constexpr const _Tp& 90838fd1498Szrj _M_get() const noexcept 90938fd1498Szrj { 91038fd1498Szrj __glibcxx_assert(this->_M_is_engaged()); 91138fd1498Szrj return this->_M_payload._M_payload; 91238fd1498Szrj } 91338fd1498Szrj 91438fd1498Szrj private: 91538fd1498Szrj _Optional_payload<_Tp> _M_payload; 91638fd1498Szrj }; 91738fd1498Szrj 91838fd1498Szrj template<typename _Tp> 91938fd1498Szrj class optional; 92038fd1498Szrj 92138fd1498Szrj template<typename _Tp, typename _Up> 92238fd1498Szrj using __converts_from_optional = 92338fd1498Szrj __or_<is_constructible<_Tp, const optional<_Up>&>, 92438fd1498Szrj is_constructible<_Tp, optional<_Up>&>, 92538fd1498Szrj is_constructible<_Tp, const optional<_Up>&&>, 92638fd1498Szrj is_constructible<_Tp, optional<_Up>&&>, 92738fd1498Szrj is_convertible<const optional<_Up>&, _Tp>, 92838fd1498Szrj is_convertible<optional<_Up>&, _Tp>, 92938fd1498Szrj is_convertible<const optional<_Up>&&, _Tp>, 93038fd1498Szrj is_convertible<optional<_Up>&&, _Tp>>; 93138fd1498Szrj 93238fd1498Szrj template<typename _Tp, typename _Up> 93338fd1498Szrj using __assigns_from_optional = 93438fd1498Szrj __or_<is_assignable<_Tp&, const optional<_Up>&>, 93538fd1498Szrj is_assignable<_Tp&, optional<_Up>&>, 93638fd1498Szrj is_assignable<_Tp&, const optional<_Up>&&>, 93738fd1498Szrj is_assignable<_Tp&, optional<_Up>&&>>; 93838fd1498Szrj 93938fd1498Szrj /** 94038fd1498Szrj * @brief Class template for optional values. 94138fd1498Szrj */ 94238fd1498Szrj template<typename _Tp> 94338fd1498Szrj class optional 94438fd1498Szrj : private _Optional_base<_Tp>, 94538fd1498Szrj private _Enable_copy_move< 94638fd1498Szrj // Copy constructor. 94738fd1498Szrj is_copy_constructible<_Tp>::value, 94838fd1498Szrj // Copy assignment. 94938fd1498Szrj __and_<is_copy_constructible<_Tp>, is_copy_assignable<_Tp>>::value, 95038fd1498Szrj // Move constructor. 95138fd1498Szrj is_move_constructible<_Tp>::value, 95238fd1498Szrj // Move assignment. 95338fd1498Szrj __and_<is_move_constructible<_Tp>, is_move_assignable<_Tp>>::value, 95438fd1498Szrj // Unique tag type. 95538fd1498Szrj optional<_Tp>> 95638fd1498Szrj { 95738fd1498Szrj static_assert(!is_same_v<remove_cv_t<_Tp>, nullopt_t>); 95838fd1498Szrj static_assert(!is_same_v<remove_cv_t<_Tp>, in_place_t>); 95938fd1498Szrj static_assert(!is_reference_v<_Tp>); 96038fd1498Szrj 96138fd1498Szrj private: 96238fd1498Szrj using _Base = _Optional_base<_Tp>; 96338fd1498Szrj 96438fd1498Szrj public: 96538fd1498Szrj using value_type = _Tp; 96638fd1498Szrj 96738fd1498Szrj constexpr optional() = default; 96838fd1498Szrj 96938fd1498Szrj constexpr optional(nullopt_t) noexcept { } 97038fd1498Szrj 97138fd1498Szrj // Converting constructors for engaged optionals. 97238fd1498Szrj template <typename _Up = _Tp, 97338fd1498Szrj enable_if_t<__and_< 97438fd1498Szrj __not_<is_same<optional<_Tp>, decay_t<_Up>>>, 97538fd1498Szrj __not_<is_same<in_place_t, decay_t<_Up>>>, 97638fd1498Szrj is_constructible<_Tp, _Up&&>, 97738fd1498Szrj is_convertible<_Up&&, _Tp> 97838fd1498Szrj >::value, bool> = true> 97938fd1498Szrj constexpr optional(_Up&& __t) 98038fd1498Szrj : _Base(std::in_place, std::forward<_Up>(__t)) { } 98138fd1498Szrj 98238fd1498Szrj template <typename _Up = _Tp, 98338fd1498Szrj enable_if_t<__and_< 98438fd1498Szrj __not_<is_same<optional<_Tp>, decay_t<_Up>>>, 98538fd1498Szrj __not_<is_same<in_place_t, decay_t<_Up>>>, 98638fd1498Szrj is_constructible<_Tp, _Up&&>, 98738fd1498Szrj __not_<is_convertible<_Up&&, _Tp>> 98838fd1498Szrj >::value, bool> = false> 98938fd1498Szrj explicit constexpr optional(_Up&& __t) 99038fd1498Szrj : _Base(std::in_place, std::forward<_Up>(__t)) { } 99138fd1498Szrj 99238fd1498Szrj template <typename _Up, 99338fd1498Szrj enable_if_t<__and_< 99438fd1498Szrj __not_<is_same<_Tp, _Up>>, 99538fd1498Szrj is_constructible<_Tp, const _Up&>, 99638fd1498Szrj is_convertible<const _Up&, _Tp>, 99738fd1498Szrj __not_<__converts_from_optional<_Tp, _Up>> 99838fd1498Szrj >::value, bool> = true> 99938fd1498Szrj constexpr optional(const optional<_Up>& __t) 100038fd1498Szrj { 100138fd1498Szrj if (__t) 100238fd1498Szrj emplace(*__t); 100338fd1498Szrj } 100438fd1498Szrj 100538fd1498Szrj template <typename _Up, 100638fd1498Szrj enable_if_t<__and_< 100738fd1498Szrj __not_<is_same<_Tp, _Up>>, 100838fd1498Szrj is_constructible<_Tp, const _Up&>, 100938fd1498Szrj __not_<is_convertible<const _Up&, _Tp>>, 101038fd1498Szrj __not_<__converts_from_optional<_Tp, _Up>> 101138fd1498Szrj >::value, bool> = false> 101238fd1498Szrj explicit constexpr optional(const optional<_Up>& __t) 101338fd1498Szrj { 101438fd1498Szrj if (__t) 101538fd1498Szrj emplace(*__t); 101638fd1498Szrj } 101738fd1498Szrj 101838fd1498Szrj template <typename _Up, 101938fd1498Szrj enable_if_t<__and_< 102038fd1498Szrj __not_<is_same<_Tp, _Up>>, 102138fd1498Szrj is_constructible<_Tp, _Up&&>, 102238fd1498Szrj is_convertible<_Up&&, _Tp>, 102338fd1498Szrj __not_<__converts_from_optional<_Tp, _Up>> 102438fd1498Szrj >::value, bool> = true> 102538fd1498Szrj constexpr optional(optional<_Up>&& __t) 102638fd1498Szrj { 102738fd1498Szrj if (__t) 102838fd1498Szrj emplace(std::move(*__t)); 102938fd1498Szrj } 103038fd1498Szrj 103138fd1498Szrj template <typename _Up, 103238fd1498Szrj enable_if_t<__and_< 103338fd1498Szrj __not_<is_same<_Tp, _Up>>, 103438fd1498Szrj is_constructible<_Tp, _Up&&>, 103538fd1498Szrj __not_<is_convertible<_Up&&, _Tp>>, 103638fd1498Szrj __not_<__converts_from_optional<_Tp, _Up>> 103738fd1498Szrj >::value, bool> = false> 103838fd1498Szrj explicit constexpr optional(optional<_Up>&& __t) 103938fd1498Szrj { 104038fd1498Szrj if (__t) 104138fd1498Szrj emplace(std::move(*__t)); 104238fd1498Szrj } 104338fd1498Szrj 104438fd1498Szrj template<typename... _Args, 104538fd1498Szrj enable_if_t<is_constructible_v<_Tp, _Args&&...>, bool> = false> 104638fd1498Szrj explicit constexpr optional(in_place_t, _Args&&... __args) 104738fd1498Szrj : _Base(std::in_place, std::forward<_Args>(__args)...) { } 104838fd1498Szrj 104938fd1498Szrj template<typename _Up, typename... _Args, 105038fd1498Szrj enable_if_t<is_constructible_v<_Tp, 105138fd1498Szrj initializer_list<_Up>&, 105238fd1498Szrj _Args&&...>, bool> = false> 105338fd1498Szrj explicit constexpr optional(in_place_t, 105438fd1498Szrj initializer_list<_Up> __il, 105538fd1498Szrj _Args&&... __args) 105638fd1498Szrj : _Base(std::in_place, __il, std::forward<_Args>(__args)...) { } 105738fd1498Szrj 105838fd1498Szrj // Assignment operators. 105938fd1498Szrj optional& 106038fd1498Szrj operator=(nullopt_t) noexcept 106138fd1498Szrj { 106238fd1498Szrj this->_M_reset(); 106338fd1498Szrj return *this; 106438fd1498Szrj } 106538fd1498Szrj 106638fd1498Szrj template<typename _Up = _Tp> 106738fd1498Szrj enable_if_t<__and_< 106838fd1498Szrj __not_<is_same<optional<_Tp>, decay_t<_Up>>>, 106938fd1498Szrj is_constructible<_Tp, _Up>, 107038fd1498Szrj __not_<__and_<is_scalar<_Tp>, 107138fd1498Szrj is_same<_Tp, decay_t<_Up>>>>, 107238fd1498Szrj is_assignable<_Tp&, _Up>>::value, 107338fd1498Szrj optional&> 107438fd1498Szrj operator=(_Up&& __u) 107538fd1498Szrj { 107638fd1498Szrj if (this->_M_is_engaged()) 107738fd1498Szrj this->_M_get() = std::forward<_Up>(__u); 107838fd1498Szrj else 107938fd1498Szrj this->_M_construct(std::forward<_Up>(__u)); 108038fd1498Szrj 108138fd1498Szrj return *this; 108238fd1498Szrj } 108338fd1498Szrj 108438fd1498Szrj template<typename _Up> 108538fd1498Szrj enable_if_t<__and_< 108638fd1498Szrj __not_<is_same<_Tp, _Up>>, 108738fd1498Szrj is_constructible<_Tp, const _Up&>, 108838fd1498Szrj is_assignable<_Tp&, _Up>, 108938fd1498Szrj __not_<__converts_from_optional<_Tp, _Up>>, 109038fd1498Szrj __not_<__assigns_from_optional<_Tp, _Up>> 109138fd1498Szrj >::value, 109238fd1498Szrj optional&> 109338fd1498Szrj operator=(const optional<_Up>& __u) 109438fd1498Szrj { 109538fd1498Szrj if (__u) 109638fd1498Szrj { 109738fd1498Szrj if (this->_M_is_engaged()) 109838fd1498Szrj this->_M_get() = *__u; 109938fd1498Szrj else 110038fd1498Szrj this->_M_construct(*__u); 110138fd1498Szrj } 110238fd1498Szrj else 110338fd1498Szrj { 110438fd1498Szrj this->_M_reset(); 110538fd1498Szrj } 110638fd1498Szrj return *this; 110738fd1498Szrj } 110838fd1498Szrj 110938fd1498Szrj template<typename _Up> 111038fd1498Szrj enable_if_t<__and_< 111138fd1498Szrj __not_<is_same<_Tp, _Up>>, 111238fd1498Szrj is_constructible<_Tp, _Up>, 111338fd1498Szrj is_assignable<_Tp&, _Up>, 111438fd1498Szrj __not_<__converts_from_optional<_Tp, _Up>>, 111538fd1498Szrj __not_<__assigns_from_optional<_Tp, _Up>> 111638fd1498Szrj >::value, 111738fd1498Szrj optional&> 111838fd1498Szrj operator=(optional<_Up>&& __u) 111938fd1498Szrj { 112038fd1498Szrj if (__u) 112138fd1498Szrj { 112238fd1498Szrj if (this->_M_is_engaged()) 112338fd1498Szrj this->_M_get() = std::move(*__u); 112438fd1498Szrj else 112538fd1498Szrj this->_M_construct(std::move(*__u)); 112638fd1498Szrj } 112738fd1498Szrj else 112838fd1498Szrj { 112938fd1498Szrj this->_M_reset(); 113038fd1498Szrj } 113138fd1498Szrj 113238fd1498Szrj return *this; 113338fd1498Szrj } 113438fd1498Szrj 113538fd1498Szrj template<typename... _Args> 113638fd1498Szrj enable_if_t<is_constructible<_Tp, _Args&&...>::value, _Tp&> 113738fd1498Szrj emplace(_Args&&... __args) 113838fd1498Szrj { 113938fd1498Szrj this->_M_reset(); 114038fd1498Szrj this->_M_construct(std::forward<_Args>(__args)...); 114138fd1498Szrj return this->_M_get(); 114238fd1498Szrj } 114338fd1498Szrj 114438fd1498Szrj template<typename _Up, typename... _Args> 114538fd1498Szrj enable_if_t<is_constructible<_Tp, initializer_list<_Up>&, 114638fd1498Szrj _Args&&...>::value, _Tp&> 114738fd1498Szrj emplace(initializer_list<_Up> __il, _Args&&... __args) 114838fd1498Szrj { 114938fd1498Szrj this->_M_reset(); 115038fd1498Szrj this->_M_construct(__il, std::forward<_Args>(__args)...); 115138fd1498Szrj return this->_M_get(); 115238fd1498Szrj } 115338fd1498Szrj 115438fd1498Szrj // Destructor is implicit, implemented in _Optional_base. 115538fd1498Szrj 115638fd1498Szrj // Swap. 115738fd1498Szrj void 115838fd1498Szrj swap(optional& __other) 115938fd1498Szrj noexcept(is_nothrow_move_constructible<_Tp>() 116038fd1498Szrj && is_nothrow_swappable_v<_Tp>) 116138fd1498Szrj { 116238fd1498Szrj using std::swap; 116338fd1498Szrj 116438fd1498Szrj if (this->_M_is_engaged() && __other._M_is_engaged()) 116538fd1498Szrj swap(this->_M_get(), __other._M_get()); 116638fd1498Szrj else if (this->_M_is_engaged()) 116738fd1498Szrj { 116838fd1498Szrj __other._M_construct(std::move(this->_M_get())); 116938fd1498Szrj this->_M_destruct(); 117038fd1498Szrj } 117138fd1498Szrj else if (__other._M_is_engaged()) 117238fd1498Szrj { 117338fd1498Szrj this->_M_construct(std::move(__other._M_get())); 117438fd1498Szrj __other._M_destruct(); 117538fd1498Szrj } 117638fd1498Szrj } 117738fd1498Szrj 117838fd1498Szrj // Observers. 117938fd1498Szrj constexpr const _Tp* 118038fd1498Szrj operator->() const 118138fd1498Szrj { return std::__addressof(this->_M_get()); } 118238fd1498Szrj 1183*58e805e6Szrj constexpr 118438fd1498Szrj _Tp* 118538fd1498Szrj operator->() 118638fd1498Szrj { return std::__addressof(this->_M_get()); } 118738fd1498Szrj 118838fd1498Szrj constexpr const _Tp& 118938fd1498Szrj operator*() const& 119038fd1498Szrj { return this->_M_get(); } 119138fd1498Szrj 119238fd1498Szrj constexpr _Tp& 119338fd1498Szrj operator*()& 119438fd1498Szrj { return this->_M_get(); } 119538fd1498Szrj 119638fd1498Szrj constexpr _Tp&& 119738fd1498Szrj operator*()&& 119838fd1498Szrj { return std::move(this->_M_get()); } 119938fd1498Szrj 120038fd1498Szrj constexpr const _Tp&& 120138fd1498Szrj operator*() const&& 120238fd1498Szrj { return std::move(this->_M_get()); } 120338fd1498Szrj 120438fd1498Szrj constexpr explicit operator bool() const noexcept 120538fd1498Szrj { return this->_M_is_engaged(); } 120638fd1498Szrj 120738fd1498Szrj constexpr bool has_value() const noexcept 120838fd1498Szrj { return this->_M_is_engaged(); } 120938fd1498Szrj 121038fd1498Szrj constexpr const _Tp& 121138fd1498Szrj value() const& 121238fd1498Szrj { 121338fd1498Szrj return this->_M_is_engaged() 121438fd1498Szrj ? this->_M_get() 121538fd1498Szrj : (__throw_bad_optional_access(), 121638fd1498Szrj this->_M_get()); 121738fd1498Szrj } 121838fd1498Szrj 121938fd1498Szrj constexpr _Tp& 122038fd1498Szrj value()& 122138fd1498Szrj { 122238fd1498Szrj return this->_M_is_engaged() 122338fd1498Szrj ? this->_M_get() 122438fd1498Szrj : (__throw_bad_optional_access(), 122538fd1498Szrj this->_M_get()); 122638fd1498Szrj } 122738fd1498Szrj 122838fd1498Szrj constexpr _Tp&& 122938fd1498Szrj value()&& 123038fd1498Szrj { 123138fd1498Szrj return this->_M_is_engaged() 123238fd1498Szrj ? std::move(this->_M_get()) 123338fd1498Szrj : (__throw_bad_optional_access(), 123438fd1498Szrj std::move(this->_M_get())); 123538fd1498Szrj } 123638fd1498Szrj 123738fd1498Szrj constexpr const _Tp&& 123838fd1498Szrj value() const&& 123938fd1498Szrj { 124038fd1498Szrj return this->_M_is_engaged() 124138fd1498Szrj ? std::move(this->_M_get()) 124238fd1498Szrj : (__throw_bad_optional_access(), 124338fd1498Szrj std::move(this->_M_get())); 124438fd1498Szrj } 124538fd1498Szrj 124638fd1498Szrj template<typename _Up> 124738fd1498Szrj constexpr _Tp 124838fd1498Szrj value_or(_Up&& __u) const& 124938fd1498Szrj { 125038fd1498Szrj static_assert(is_copy_constructible_v<_Tp>); 125138fd1498Szrj static_assert(is_convertible_v<_Up&&, _Tp>); 125238fd1498Szrj 125338fd1498Szrj return this->_M_is_engaged() 125438fd1498Szrj ? this->_M_get() 125538fd1498Szrj : static_cast<_Tp>(std::forward<_Up>(__u)); 125638fd1498Szrj } 125738fd1498Szrj 125838fd1498Szrj template<typename _Up> 125938fd1498Szrj _Tp 126038fd1498Szrj value_or(_Up&& __u) && 126138fd1498Szrj { 126238fd1498Szrj static_assert(is_move_constructible_v<_Tp>); 126338fd1498Szrj static_assert(is_convertible_v<_Up&&, _Tp>); 126438fd1498Szrj 126538fd1498Szrj return this->_M_is_engaged() 126638fd1498Szrj ? std::move(this->_M_get()) 126738fd1498Szrj : static_cast<_Tp>(std::forward<_Up>(__u)); 126838fd1498Szrj } 126938fd1498Szrj void reset() noexcept { this->_M_reset(); } 127038fd1498Szrj }; 127138fd1498Szrj 127238fd1498Szrj template<typename _Tp> 127338fd1498Szrj using __optional_relop_t = 127438fd1498Szrj enable_if_t<is_convertible<_Tp, bool>::value, bool>; 127538fd1498Szrj 127638fd1498Szrj // Comparisons between optional values. 127738fd1498Szrj template<typename _Tp, typename _Up> 127838fd1498Szrj constexpr auto 127938fd1498Szrj operator==(const optional<_Tp>& __lhs, const optional<_Up>& __rhs) 128038fd1498Szrj -> __optional_relop_t<decltype(declval<_Tp>() == declval<_Up>())> 128138fd1498Szrj { 128238fd1498Szrj return static_cast<bool>(__lhs) == static_cast<bool>(__rhs) 128338fd1498Szrj && (!__lhs || *__lhs == *__rhs); 128438fd1498Szrj } 128538fd1498Szrj 128638fd1498Szrj template<typename _Tp, typename _Up> 128738fd1498Szrj constexpr auto 128838fd1498Szrj operator!=(const optional<_Tp>& __lhs, const optional<_Up>& __rhs) 128938fd1498Szrj -> __optional_relop_t<decltype(declval<_Tp>() != declval<_Up>())> 129038fd1498Szrj { 129138fd1498Szrj return static_cast<bool>(__lhs) != static_cast<bool>(__rhs) 129238fd1498Szrj || (static_cast<bool>(__lhs) && *__lhs != *__rhs); 129338fd1498Szrj } 129438fd1498Szrj 129538fd1498Szrj template<typename _Tp, typename _Up> 129638fd1498Szrj constexpr auto 129738fd1498Szrj operator<(const optional<_Tp>& __lhs, const optional<_Up>& __rhs) 129838fd1498Szrj -> __optional_relop_t<decltype(declval<_Tp>() < declval<_Up>())> 129938fd1498Szrj { 130038fd1498Szrj return static_cast<bool>(__rhs) && (!__lhs || *__lhs < *__rhs); 130138fd1498Szrj } 130238fd1498Szrj 130338fd1498Szrj template<typename _Tp, typename _Up> 130438fd1498Szrj constexpr auto 130538fd1498Szrj operator>(const optional<_Tp>& __lhs, const optional<_Up>& __rhs) 130638fd1498Szrj -> __optional_relop_t<decltype(declval<_Tp>() > declval<_Up>())> 130738fd1498Szrj { 130838fd1498Szrj return static_cast<bool>(__lhs) && (!__rhs || *__lhs > *__rhs); 130938fd1498Szrj } 131038fd1498Szrj 131138fd1498Szrj template<typename _Tp, typename _Up> 131238fd1498Szrj constexpr auto 131338fd1498Szrj operator<=(const optional<_Tp>& __lhs, const optional<_Up>& __rhs) 131438fd1498Szrj -> __optional_relop_t<decltype(declval<_Tp>() <= declval<_Up>())> 131538fd1498Szrj { 131638fd1498Szrj return !__lhs || (static_cast<bool>(__rhs) && *__lhs <= *__rhs); 131738fd1498Szrj } 131838fd1498Szrj 131938fd1498Szrj template<typename _Tp, typename _Up> 132038fd1498Szrj constexpr auto 132138fd1498Szrj operator>=(const optional<_Tp>& __lhs, const optional<_Up>& __rhs) 132238fd1498Szrj -> __optional_relop_t<decltype(declval<_Tp>() >= declval<_Up>())> 132338fd1498Szrj { 132438fd1498Szrj return !__rhs || (static_cast<bool>(__lhs) && *__lhs >= *__rhs); 132538fd1498Szrj } 132638fd1498Szrj 132738fd1498Szrj // Comparisons with nullopt. 132838fd1498Szrj template<typename _Tp> 132938fd1498Szrj constexpr bool 133038fd1498Szrj operator==(const optional<_Tp>& __lhs, nullopt_t) noexcept 133138fd1498Szrj { return !__lhs; } 133238fd1498Szrj 133338fd1498Szrj template<typename _Tp> 133438fd1498Szrj constexpr bool 133538fd1498Szrj operator==(nullopt_t, const optional<_Tp>& __rhs) noexcept 133638fd1498Szrj { return !__rhs; } 133738fd1498Szrj 133838fd1498Szrj template<typename _Tp> 133938fd1498Szrj constexpr bool 134038fd1498Szrj operator!=(const optional<_Tp>& __lhs, nullopt_t) noexcept 134138fd1498Szrj { return static_cast<bool>(__lhs); } 134238fd1498Szrj 134338fd1498Szrj template<typename _Tp> 134438fd1498Szrj constexpr bool 134538fd1498Szrj operator!=(nullopt_t, const optional<_Tp>& __rhs) noexcept 134638fd1498Szrj { return static_cast<bool>(__rhs); } 134738fd1498Szrj 134838fd1498Szrj template<typename _Tp> 134938fd1498Szrj constexpr bool 135038fd1498Szrj operator<(const optional<_Tp>& /* __lhs */, nullopt_t) noexcept 135138fd1498Szrj { return false; } 135238fd1498Szrj 135338fd1498Szrj template<typename _Tp> 135438fd1498Szrj constexpr bool 135538fd1498Szrj operator<(nullopt_t, const optional<_Tp>& __rhs) noexcept 135638fd1498Szrj { return static_cast<bool>(__rhs); } 135738fd1498Szrj 135838fd1498Szrj template<typename _Tp> 135938fd1498Szrj constexpr bool 136038fd1498Szrj operator>(const optional<_Tp>& __lhs, nullopt_t) noexcept 136138fd1498Szrj { return static_cast<bool>(__lhs); } 136238fd1498Szrj 136338fd1498Szrj template<typename _Tp> 136438fd1498Szrj constexpr bool 136538fd1498Szrj operator>(nullopt_t, const optional<_Tp>& /* __rhs */) noexcept 136638fd1498Szrj { return false; } 136738fd1498Szrj 136838fd1498Szrj template<typename _Tp> 136938fd1498Szrj constexpr bool 137038fd1498Szrj operator<=(const optional<_Tp>& __lhs, nullopt_t) noexcept 137138fd1498Szrj { return !__lhs; } 137238fd1498Szrj 137338fd1498Szrj template<typename _Tp> 137438fd1498Szrj constexpr bool 137538fd1498Szrj operator<=(nullopt_t, const optional<_Tp>& /* __rhs */) noexcept 137638fd1498Szrj { return true; } 137738fd1498Szrj 137838fd1498Szrj template<typename _Tp> 137938fd1498Szrj constexpr bool 138038fd1498Szrj operator>=(const optional<_Tp>& /* __lhs */, nullopt_t) noexcept 138138fd1498Szrj { return true; } 138238fd1498Szrj 138338fd1498Szrj template<typename _Tp> 138438fd1498Szrj constexpr bool 138538fd1498Szrj operator>=(nullopt_t, const optional<_Tp>& __rhs) noexcept 138638fd1498Szrj { return !__rhs; } 138738fd1498Szrj 138838fd1498Szrj // Comparisons with value type. 138938fd1498Szrj template<typename _Tp, typename _Up> 139038fd1498Szrj constexpr auto 139138fd1498Szrj operator==(const optional<_Tp>& __lhs, const _Up& __rhs) 139238fd1498Szrj -> __optional_relop_t<decltype(declval<_Tp>() == declval<_Up>())> 139338fd1498Szrj { return __lhs && *__lhs == __rhs; } 139438fd1498Szrj 139538fd1498Szrj template<typename _Tp, typename _Up> 139638fd1498Szrj constexpr auto 139738fd1498Szrj operator==(const _Up& __lhs, const optional<_Tp>& __rhs) 139838fd1498Szrj -> __optional_relop_t<decltype(declval<_Up>() == declval<_Tp>())> 139938fd1498Szrj { return __rhs && __lhs == *__rhs; } 140038fd1498Szrj 140138fd1498Szrj template<typename _Tp, typename _Up> 140238fd1498Szrj constexpr auto 140338fd1498Szrj operator!=(const optional<_Tp>& __lhs, const _Up& __rhs) 140438fd1498Szrj -> __optional_relop_t<decltype(declval<_Tp>() != declval<_Up>())> 140538fd1498Szrj { return !__lhs || *__lhs != __rhs; } 140638fd1498Szrj 140738fd1498Szrj template<typename _Tp, typename _Up> 140838fd1498Szrj constexpr auto 140938fd1498Szrj operator!=(const _Up& __lhs, const optional<_Tp>& __rhs) 141038fd1498Szrj -> __optional_relop_t<decltype(declval<_Up>() != declval<_Tp>())> 141138fd1498Szrj { return !__rhs || __lhs != *__rhs; } 141238fd1498Szrj 141338fd1498Szrj template<typename _Tp, typename _Up> 141438fd1498Szrj constexpr auto 141538fd1498Szrj operator<(const optional<_Tp>& __lhs, const _Up& __rhs) 141638fd1498Szrj -> __optional_relop_t<decltype(declval<_Tp>() < declval<_Up>())> 141738fd1498Szrj { return !__lhs || *__lhs < __rhs; } 141838fd1498Szrj 141938fd1498Szrj template<typename _Tp, typename _Up> 142038fd1498Szrj constexpr auto 142138fd1498Szrj operator<(const _Up& __lhs, const optional<_Tp>& __rhs) 142238fd1498Szrj -> __optional_relop_t<decltype(declval<_Up>() < declval<_Tp>())> 142338fd1498Szrj { return __rhs && __lhs < *__rhs; } 142438fd1498Szrj 142538fd1498Szrj template<typename _Tp, typename _Up> 142638fd1498Szrj constexpr auto 142738fd1498Szrj operator>(const optional<_Tp>& __lhs, const _Up& __rhs) 142838fd1498Szrj -> __optional_relop_t<decltype(declval<_Tp>() > declval<_Up>())> 142938fd1498Szrj { return __lhs && *__lhs > __rhs; } 143038fd1498Szrj 143138fd1498Szrj template<typename _Tp, typename _Up> 143238fd1498Szrj constexpr auto 143338fd1498Szrj operator>(const _Up& __lhs, const optional<_Tp>& __rhs) 143438fd1498Szrj -> __optional_relop_t<decltype(declval<_Up>() > declval<_Tp>())> 143538fd1498Szrj { return !__rhs || __lhs > *__rhs; } 143638fd1498Szrj 143738fd1498Szrj template<typename _Tp, typename _Up> 143838fd1498Szrj constexpr auto 143938fd1498Szrj operator<=(const optional<_Tp>& __lhs, const _Up& __rhs) 144038fd1498Szrj -> __optional_relop_t<decltype(declval<_Tp>() <= declval<_Up>())> 144138fd1498Szrj { return !__lhs || *__lhs <= __rhs; } 144238fd1498Szrj 144338fd1498Szrj template<typename _Tp, typename _Up> 144438fd1498Szrj constexpr auto 144538fd1498Szrj operator<=(const _Up& __lhs, const optional<_Tp>& __rhs) 144638fd1498Szrj -> __optional_relop_t<decltype(declval<_Up>() <= declval<_Tp>())> 144738fd1498Szrj { return __rhs && __lhs <= *__rhs; } 144838fd1498Szrj 144938fd1498Szrj template<typename _Tp, typename _Up> 145038fd1498Szrj constexpr auto 145138fd1498Szrj operator>=(const optional<_Tp>& __lhs, const _Up& __rhs) 145238fd1498Szrj -> __optional_relop_t<decltype(declval<_Tp>() >= declval<_Up>())> 145338fd1498Szrj { return __lhs && *__lhs >= __rhs; } 145438fd1498Szrj 145538fd1498Szrj template<typename _Tp, typename _Up> 145638fd1498Szrj constexpr auto 145738fd1498Szrj operator>=(const _Up& __lhs, const optional<_Tp>& __rhs) 145838fd1498Szrj -> __optional_relop_t<decltype(declval<_Up>() >= declval<_Tp>())> 145938fd1498Szrj { return !__rhs || __lhs >= *__rhs; } 146038fd1498Szrj 146138fd1498Szrj // Swap and creation functions. 146238fd1498Szrj 146338fd1498Szrj // _GLIBCXX_RESOLVE_LIB_DEFECTS 146438fd1498Szrj // 2748. swappable traits for optionals 146538fd1498Szrj template<typename _Tp> 146638fd1498Szrj inline enable_if_t<is_move_constructible_v<_Tp> && is_swappable_v<_Tp>> 146738fd1498Szrj swap(optional<_Tp>& __lhs, optional<_Tp>& __rhs) 146838fd1498Szrj noexcept(noexcept(__lhs.swap(__rhs))) 146938fd1498Szrj { __lhs.swap(__rhs); } 147038fd1498Szrj 147138fd1498Szrj template<typename _Tp> 147238fd1498Szrj enable_if_t<!(is_move_constructible_v<_Tp> && is_swappable_v<_Tp>)> 147338fd1498Szrj swap(optional<_Tp>&, optional<_Tp>&) = delete; 147438fd1498Szrj 147538fd1498Szrj template<typename _Tp> 147638fd1498Szrj constexpr optional<decay_t<_Tp>> 147738fd1498Szrj make_optional(_Tp&& __t) 147838fd1498Szrj { return optional<decay_t<_Tp>> { std::forward<_Tp>(__t) }; } 147938fd1498Szrj 148038fd1498Szrj template<typename _Tp, typename ..._Args> 148138fd1498Szrj constexpr optional<_Tp> 148238fd1498Szrj make_optional(_Args&&... __args) 148338fd1498Szrj { return optional<_Tp> { in_place, std::forward<_Args>(__args)... }; } 148438fd1498Szrj 148538fd1498Szrj template<typename _Tp, typename _Up, typename ..._Args> 148638fd1498Szrj constexpr optional<_Tp> 148738fd1498Szrj make_optional(initializer_list<_Up> __il, _Args&&... __args) 148838fd1498Szrj { return optional<_Tp> { in_place, __il, std::forward<_Args>(__args)... }; } 148938fd1498Szrj 149038fd1498Szrj // Hash. 149138fd1498Szrj 149238fd1498Szrj template<typename _Tp, typename _Up = remove_const_t<_Tp>, 149338fd1498Szrj bool = __poison_hash<_Up>::__enable_hash_call> 149438fd1498Szrj struct __optional_hash_call_base 149538fd1498Szrj { 149638fd1498Szrj size_t 149738fd1498Szrj operator()(const optional<_Tp>& __t) const 149838fd1498Szrj noexcept(noexcept(hash<_Up>{}(*__t))) 149938fd1498Szrj { 150038fd1498Szrj // We pick an arbitrary hash for disengaged optionals which hopefully 150138fd1498Szrj // usual values of _Tp won't typically hash to. 150238fd1498Szrj constexpr size_t __magic_disengaged_hash = static_cast<size_t>(-3333); 150338fd1498Szrj return __t ? hash<_Up>{}(*__t) : __magic_disengaged_hash; 150438fd1498Szrj } 150538fd1498Szrj }; 150638fd1498Szrj 150738fd1498Szrj template<typename _Tp, typename _Up> 150838fd1498Szrj struct __optional_hash_call_base<_Tp, _Up, false> {}; 150938fd1498Szrj 151038fd1498Szrj template<typename _Tp> 151138fd1498Szrj struct hash<optional<_Tp>> 151238fd1498Szrj : private __poison_hash<remove_const_t<_Tp>>, 151338fd1498Szrj public __optional_hash_call_base<_Tp> 151438fd1498Szrj { 151538fd1498Szrj using result_type [[__deprecated__]] = size_t; 151638fd1498Szrj using argument_type [[__deprecated__]] = optional<_Tp>; 151738fd1498Szrj }; 151838fd1498Szrj 151938fd1498Szrj template<typename _Tp> 152038fd1498Szrj struct __is_fast_hash<hash<optional<_Tp>>> : __is_fast_hash<hash<_Tp>> 152138fd1498Szrj { }; 152238fd1498Szrj 152338fd1498Szrj /// @} 152438fd1498Szrj 152538fd1498Szrj#if __cpp_deduction_guides >= 201606 152638fd1498Szrj template <typename _Tp> optional(_Tp) -> optional<_Tp>; 152738fd1498Szrj#endif 152838fd1498Szrj 152938fd1498Szrj_GLIBCXX_END_NAMESPACE_VERSION 153038fd1498Szrj} // namespace std 153138fd1498Szrj 153238fd1498Szrj#endif // C++17 153338fd1498Szrj 153438fd1498Szrj#endif // _GLIBCXX_OPTIONAL 1535