xref: /dflybsd-src/contrib/gcc-8.0/libstdc++-v3/include/std/optional (revision 95059079af47f9a66a175f374f2da1a5020e3255)
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