LCOV - code coverage report
Current view: top level - usr/include/c++/8 - optional (source / functions) Hit Total Coverage
Test: Coverage example Lines: 10 14 71.4 %
Date: 2021-12-02 17:21:05 Functions: 12 18 66.7 %

          Line data    Source code
       1             : // <optional> -*- C++ -*-
       2             : 
       3             : // Copyright (C) 2013-2018 Free Software Foundation, Inc.
       4             : //
       5             : // This file is part of the GNU ISO C++ Library.  This library is free
       6             : // software; you can redistribute it and/or modify it under the
       7             : // terms of the GNU General Public License as published by the
       8             : // Free Software Foundation; either version 3, or (at your option)
       9             : // any later version.
      10             : 
      11             : // This library is distributed in the hope that it will be useful,
      12             : // but WITHOUT ANY WARRANTY; without even the implied warranty of
      13             : // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      14             : // GNU General Public License for more details.
      15             : 
      16             : // Under Section 7 of GPL version 3, you are granted additional
      17             : // permissions described in the GCC Runtime Library Exception, version
      18             : // 3.1, as published by the Free Software Foundation.
      19             : 
      20             : // You should have received a copy of the GNU General Public License and
      21             : // a copy of the GCC Runtime Library Exception along with this program;
      22             : // see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
      23             : // <http://www.gnu.org/licenses/>.
      24             : 
      25             : /** @file include/optional
      26             :  *  This is a Standard C++ Library header.
      27             :  */
      28             : 
      29             : #ifndef _GLIBCXX_OPTIONAL
      30             : #define _GLIBCXX_OPTIONAL 1
      31             : 
      32             : #pragma GCC system_header
      33             : 
      34             : #if __cplusplus >= 201703L
      35             : 
      36             : #include <utility>
      37             : #include <type_traits>
      38             : #include <stdexcept>
      39             : #include <new>
      40             : #include <initializer_list>
      41             : #include <bits/functexcept.h>
      42             : #include <bits/functional_hash.h>
      43             : #include <bits/enable_special_members.h>
      44             : 
      45             : namespace std _GLIBCXX_VISIBILITY(default)
      46             : {
      47             : _GLIBCXX_BEGIN_NAMESPACE_VERSION
      48             : 
      49             :   /**
      50             :    *  @addtogroup utilities
      51             :    *  @{
      52             :    */
      53             : 
      54             : #define __cpp_lib_optional 201606L
      55             : 
      56             :   template<typename _Tp>
      57             :     class optional;
      58             : 
      59             :   /// Tag type to disengage optional objects.
      60             :   struct nullopt_t
      61             :   {
      62             :     // Do not user-declare default constructor at all for
      63             :     // optional_value = {} syntax to work.
      64             :     // nullopt_t() = delete;
      65             : 
      66             :     // Used for constructing nullopt.
      67             :     enum class _Construct { _Token };
      68             : 
      69             :     // Must be constexpr for nullopt_t to be literal.
      70             :     explicit constexpr nullopt_t(_Construct) { }
      71             :   };
      72             : 
      73             :   /// Tag to disengage optional objects.
      74             :   inline constexpr nullopt_t nullopt { nullopt_t::_Construct::_Token };
      75             : 
      76             :   /**
      77             :    *  @brief Exception class thrown when a disengaged optional object is
      78             :    *  dereferenced.
      79             :    *  @ingroup exceptions
      80             :    */
      81             :   class bad_optional_access : public exception
      82             :   {
      83             :   public:
      84             :     bad_optional_access() { }
      85             : 
      86             :     virtual const char* what() const noexcept override
      87             :     { return "bad optional access"; }
      88             : 
      89             :     virtual ~bad_optional_access() noexcept = default;
      90             :   };
      91             : 
      92             :   void
      93             :   __throw_bad_optional_access()
      94             :   __attribute__((__noreturn__));
      95             : 
      96             :   // XXX Does not belong here.
      97             :   inline void
      98             :   __throw_bad_optional_access()
      99             :   { _GLIBCXX_THROW_OR_ABORT(bad_optional_access()); }
     100             : 
     101             : 
     102             :   // Payload for optionals with non-trivial destructor.
     103             :   template <typename _Tp,
     104             :             bool /*_HasTrivialDestructor*/ =
     105             :               is_trivially_destructible_v<_Tp>,
     106             :             bool /*_HasTrivialCopy */ =
     107             :               is_trivially_copy_assignable_v<_Tp>
     108             :               && is_trivially_copy_constructible_v<_Tp>,
     109             :             bool /*_HasTrivialMove */ =
     110             :               is_trivially_move_assignable_v<_Tp>
     111             :               && is_trivially_move_constructible_v<_Tp>>
     112             :     struct _Optional_payload
     113             :     {
     114             :       constexpr _Optional_payload() noexcept : _M_empty() { }
     115             : 
     116             :       template <typename... _Args>
     117             :         constexpr
     118         176 :         _Optional_payload(in_place_t, _Args&&... __args)
     119         176 :         : _M_payload(std::forward<_Args>(__args)...), _M_engaged(true) { }
     120             : 
     121             :       template<typename _Up, typename... _Args>
     122             :         constexpr
     123             :         _Optional_payload(std::initializer_list<_Up> __il,
     124             :                           _Args&&... __args)
     125             :         : _M_payload(__il, std::forward<_Args>(__args)...),
     126             :           _M_engaged(true)
     127             :         { }
     128             : 
     129             :       constexpr
     130             :       _Optional_payload(bool __engaged, const _Optional_payload& __other)
     131             :       : _Optional_payload(__other)
     132             :       { }
     133             : 
     134             :       constexpr
     135             :       _Optional_payload(bool __engaged, _Optional_payload&& __other)
     136             :       : _Optional_payload(std::move(__other))
     137             :       { }
     138             : 
     139             :       constexpr
     140             :       _Optional_payload(const _Optional_payload& __other)
     141             :       {
     142             :         if (__other._M_engaged)
     143             :           this->_M_construct(__other._M_payload);
     144             :       }
     145             : 
     146             :       constexpr
     147             :       _Optional_payload(_Optional_payload&& __other)
     148             :       {
     149             :         if (__other._M_engaged)
     150             :           this->_M_construct(std::move(__other._M_payload));
     151             :       }
     152             : 
     153             :       constexpr
     154             :       _Optional_payload&
     155             :       operator=(const _Optional_payload& __other)
     156             :       {
     157             :         if (this->_M_engaged && __other._M_engaged)
     158             :           this->_M_get() = __other._M_get();
     159             :         else
     160             :           {
     161             :             if (__other._M_engaged)
     162             :               this->_M_construct(__other._M_get());
     163             :             else
     164             :               this->_M_reset();
     165             :           }
     166             :         return *this;
     167             :       }
     168             : 
     169             :       constexpr
     170             :       _Optional_payload&
     171             :       operator=(_Optional_payload&& __other)
     172             :       noexcept(__and_<is_nothrow_move_constructible<_Tp>,
     173             :                       is_nothrow_move_assignable<_Tp>>())
     174             :       {
     175             :         if (this->_M_engaged && __other._M_engaged)
     176             :           this->_M_get() = std::move(__other._M_get());
     177             :         else
     178             :           {
     179             :             if (__other._M_engaged)
     180             :               this->_M_construct(std::move(__other._M_get()));
     181             :             else
     182             :               this->_M_reset();
     183             :           }
     184             :         return *this;
     185             :       }
     186             : 
     187             :       using _Stored_type = remove_const_t<_Tp>;
     188             : 
     189             :       struct _Empty_byte { };
     190             : 
     191             :       union {
     192             :           _Empty_byte _M_empty;
     193             :           _Stored_type _M_payload;
     194             :       };
     195             :       bool _M_engaged = false;
     196             : 
     197         176 :       ~_Optional_payload()
     198             :       {
     199         176 :         if (_M_engaged)
     200         176 :           _M_payload.~_Stored_type();
     201         176 :       }
     202             : 
     203             :       template<typename... _Args>
     204             :         void
     205             :         _M_construct(_Args&&... __args)
     206             :         noexcept(is_nothrow_constructible<_Stored_type, _Args...>())
     207             :         {
     208             :           ::new ((void *) std::__addressof(this->_M_payload))
     209             :             _Stored_type(std::forward<_Args>(__args)...);
     210             :           this->_M_engaged = true;
     211             :         }
     212             : 
     213             :       // The _M_get operations have _M_engaged as a precondition.
     214             :       constexpr _Tp&
     215             :       _M_get() noexcept
     216             :       { return this->_M_payload; }
     217             : 
     218             :       constexpr const _Tp&
     219             :       _M_get() const noexcept
     220             :       { return this->_M_payload; }
     221             : 
     222             :       // _M_reset is a 'safe' operation with no precondition.
     223             :       constexpr
     224             :       void
     225             :       _M_reset() noexcept
     226             :       {
     227             :         if (this->_M_engaged)
     228             :           {
     229             :             this->_M_engaged = false;
     230             :             this->_M_payload.~_Stored_type();
     231             :           }
     232             :       }
     233             :     };
     234             : 
     235             :   // Payload for potentially-constexpr optionals.
     236             :   template <typename _Tp>
     237             :     struct _Optional_payload<_Tp, true, true, true>
     238             :     {
     239             :       constexpr _Optional_payload() noexcept
     240             :       : _M_empty(), _M_engaged(false) { }
     241             : 
     242             :       template<typename... _Args>
     243             :         constexpr
     244             :         _Optional_payload(in_place_t, _Args&&... __args)
     245             :         : _M_payload(std::forward<_Args>(__args)...), _M_engaged(true)
     246             :         { }
     247             : 
     248             :       template<typename _Up, typename... _Args>
     249             :         constexpr
     250             :         _Optional_payload(std::initializer_list<_Up> __il,
     251             :                           _Args&&... __args)
     252             :         : _M_payload(__il, std::forward<_Args>(__args)...),
     253             :           _M_engaged(true)
     254             :         { }
     255             : 
     256             :       constexpr
     257             :       _Optional_payload(bool __engaged, const _Optional_payload& __other)
     258             :       : _M_engaged(__engaged)
     259             :       {
     260             :         if (__engaged)
     261             :           _M_construct(__other._M_get());
     262             :       }
     263             : 
     264             :       constexpr
     265             :       _Optional_payload(bool __engaged, _Optional_payload&& __other)
     266             :       : _M_engaged(__engaged)
     267             :       {
     268             :         if (__engaged)
     269             :           _M_construct(std::move(__other._M_get()));
     270             :       }
     271             : 
     272             :       using _Stored_type = remove_const_t<_Tp>;
     273             : 
     274             :       struct _Empty_byte { };
     275             : 
     276             :       union {
     277             :           _Empty_byte _M_empty;
     278             :           _Stored_type _M_payload;
     279             :       };
     280             :       bool _M_engaged;
     281             : 
     282             :       // The _M_get operations have _M_engaged as a precondition.
     283             :       constexpr _Tp&
     284             :       _M_get() noexcept
     285             :       { return this->_M_payload; }
     286             : 
     287             :       constexpr const _Tp&
     288             :       _M_get() const noexcept
     289             :       { return this->_M_payload; }
     290             :     };
     291             : 
     292             :   // Payload for optionals with non-trivial copy assignment.
     293             :   template <typename _Tp>
     294             :     struct _Optional_payload<_Tp, true, false, true>
     295             :     {
     296             :       constexpr _Optional_payload() noexcept
     297             :       : _M_empty(), _M_engaged(false) { }
     298             : 
     299             :       template<typename... _Args>
     300             :         constexpr
     301             :         _Optional_payload(in_place_t, _Args&&... __args)
     302             :         : _M_payload(std::forward<_Args>(__args)...), _M_engaged(true)
     303             :         { }
     304             : 
     305             :       template<typename _Up, typename... _Args>
     306             :         constexpr
     307             :         _Optional_payload(std::initializer_list<_Up> __il,
     308             :                           _Args&&... __args)
     309             :         : _M_payload(__il, std::forward<_Args>(__args)...),
     310             :           _M_engaged(true)
     311             :         { }
     312             : 
     313             :       constexpr
     314             :       _Optional_payload(bool __engaged, const _Optional_payload& __other)
     315             :       : _M_engaged(__engaged)
     316             :       {
     317             :         if (__engaged)
     318             :           _M_construct(__other._M_get());
     319             :       }
     320             : 
     321             :       constexpr
     322             :       _Optional_payload(bool __engaged, _Optional_payload&& __other)
     323             :       : _M_engaged(__engaged)
     324             :       {
     325             :         if (__engaged)
     326             :           _M_construct(std::move(__other._M_get()));
     327             :       }
     328             : 
     329             :       _Optional_payload(const _Optional_payload&) = default;
     330             :       _Optional_payload(_Optional_payload&&) = default;
     331             : 
     332             :       constexpr
     333             :       _Optional_payload&
     334             :       operator=(const _Optional_payload& __other)
     335             :       {
     336             :         if (this->_M_engaged && __other._M_engaged)
     337             :           this->_M_get() = __other._M_get();
     338             :         else
     339             :           {
     340             :             if (__other._M_engaged)
     341             :               this->_M_construct(__other._M_get());
     342             :             else
     343             :               this->_M_reset();
     344             :           }
     345             :         return *this;
     346             :       }
     347             : 
     348             :       _Optional_payload&
     349             :       operator=(_Optional_payload&& __other) = default;
     350             : 
     351             :       using _Stored_type = remove_const_t<_Tp>;
     352             : 
     353             :       struct _Empty_byte { };
     354             : 
     355             :       union {
     356             :           _Empty_byte _M_empty;
     357             :           _Stored_type _M_payload;
     358             :       };
     359             :       bool _M_engaged;
     360             : 
     361             :       template<typename... _Args>
     362             :         void
     363             :         _M_construct(_Args&&... __args)
     364             :         noexcept(is_nothrow_constructible<_Stored_type, _Args...>())
     365             :         {
     366             :           ::new ((void *) std::__addressof(this->_M_payload))
     367             :             _Stored_type(std::forward<_Args>(__args)...);
     368             :           this->_M_engaged = true;
     369             :         }
     370             : 
     371             :       // The _M_get operations have _M_engaged as a precondition.
     372             :       constexpr _Tp&
     373             :       _M_get() noexcept
     374             :       { return this->_M_payload; }
     375             : 
     376             :       constexpr const _Tp&
     377             :       _M_get() const noexcept
     378             :       { return this->_M_payload; }
     379             : 
     380             :       // _M_reset is a 'safe' operation with no precondition.
     381             :       constexpr
     382             :       void
     383             :       _M_reset() noexcept
     384             :       {
     385             :         if (this->_M_engaged)
     386             :           {
     387             :             this->_M_engaged = false;
     388             :             this->_M_payload.~_Stored_type();
     389             :           }
     390             :       }
     391             :     };
     392             : 
     393             :   // Payload for optionals with non-trivial move assignment.
     394             :   template <typename _Tp>
     395             :     struct _Optional_payload<_Tp, true, true, false>
     396             :     {
     397             :       constexpr _Optional_payload() noexcept
     398             :       : _M_empty(), _M_engaged(false) { }
     399             : 
     400             :       template<typename... _Args>
     401             :         constexpr
     402             :         _Optional_payload(in_place_t, _Args&&... __args)
     403             :         : _M_payload(std::forward<_Args>(__args)...),
     404             :           _M_engaged(true)
     405             :         { }
     406             : 
     407             :       template<typename _Up, typename... _Args>
     408             :         constexpr
     409             :         _Optional_payload(std::initializer_list<_Up> __il,
     410             :                           _Args&&... __args)
     411             :         : _M_payload(__il, std::forward<_Args>(__args)...),
     412             :           _M_engaged(true)
     413             :         { }
     414             : 
     415             :       constexpr
     416             :       _Optional_payload(bool __engaged, const _Optional_payload& __other)
     417             :       : _M_engaged(__engaged)
     418             :       {
     419             :         if (__engaged)
     420             :           _M_construct(__other._M_get());
     421             :       }
     422             : 
     423             :       constexpr
     424             :       _Optional_payload(bool __engaged, _Optional_payload&& __other)
     425             :       : _M_engaged(__engaged)
     426             :       {
     427             :         if (__engaged)
     428             :           _M_construct(std::move(__other._M_get()));
     429             :       }
     430             : 
     431             :       _Optional_payload(const _Optional_payload&) = default;
     432             :       _Optional_payload(_Optional_payload&&) = default;
     433             : 
     434             :       _Optional_payload&
     435             :       operator=(const _Optional_payload& __other) = default;
     436             : 
     437             :       constexpr
     438             :       _Optional_payload&
     439             :       operator=(_Optional_payload&& __other)
     440             :       noexcept(__and_<is_nothrow_move_constructible<_Tp>,
     441             :                       is_nothrow_move_assignable<_Tp>>())
     442             :       {
     443             :         if (this->_M_engaged && __other._M_engaged)
     444             :           this->_M_get() = std::move(__other._M_get());
     445             :         else
     446             :           {
     447             :             if (__other._M_engaged)
     448             :               this->_M_construct(std::move(__other._M_get()));
     449             :             else
     450             :               this->_M_reset();
     451             :           }
     452             :         return *this;
     453             :       }
     454             : 
     455             :       using _Stored_type = remove_const_t<_Tp>;
     456             : 
     457             :       struct _Empty_byte { };
     458             : 
     459             :       union {
     460             :           _Empty_byte _M_empty;
     461             :           _Stored_type _M_payload;
     462             :       };
     463             :       bool _M_engaged;
     464             : 
     465             :       template<typename... _Args>
     466             :         void
     467             :         _M_construct(_Args&&... __args)
     468             :         noexcept(is_nothrow_constructible<_Stored_type, _Args...>())
     469             :         {
     470             :           ::new ((void *) std::__addressof(this->_M_payload))
     471             :             _Stored_type(std::forward<_Args>(__args)...);
     472             :           this->_M_engaged = true;
     473             :         }
     474             : 
     475             :       // The _M_get operations have _M_engaged as a precondition.
     476             :       constexpr _Tp&
     477             :       _M_get() noexcept
     478             :       { return this->_M_payload; }
     479             : 
     480             :       constexpr const _Tp&
     481             :       _M_get() const noexcept
     482             :       { return this->_M_payload; }
     483             : 
     484             :       // _M_reset is a 'safe' operation with no precondition.
     485             :       constexpr
     486             :       void
     487             :       _M_reset() noexcept
     488             :       {
     489             :         if (this->_M_engaged)
     490             :           {
     491             :             this->_M_engaged = false;
     492             :             this->_M_payload.~_Stored_type();
     493             :           }
     494             :       }
     495             :     };
     496             : 
     497             :   // Payload for optionals with non-trivial copy and move assignment.
     498             :   template <typename _Tp>
     499             :     struct _Optional_payload<_Tp, true, false, false>
     500             :     {
     501             :       constexpr _Optional_payload() noexcept
     502             :       : _M_empty(), _M_engaged(false) {}
     503             : 
     504             :       template<typename... _Args>
     505             :         constexpr
     506             :         _Optional_payload(in_place_t, _Args&&... __args)
     507             :         : _M_payload(std::forward<_Args>(__args)...),
     508             :           _M_engaged(true)
     509             :         { }
     510             : 
     511             :       template<typename _Up, typename... _Args>
     512             :         constexpr
     513             :         _Optional_payload(std::initializer_list<_Up> __il,
     514             :                           _Args&&... __args)
     515             :         : _M_payload(__il, std::forward<_Args>(__args)...),
     516             :           _M_engaged(true)
     517             :         { }
     518             : 
     519             :       constexpr
     520             :       _Optional_payload(bool __engaged, const _Optional_payload& __other)
     521             :       : _M_engaged(__engaged)
     522             :       {
     523             :         if (__engaged)
     524             :           _M_construct(__other._M_get());
     525             :       }
     526             : 
     527             :       constexpr
     528             :       _Optional_payload(bool __engaged, _Optional_payload&& __other)
     529             :       : _M_engaged(__engaged)
     530             :       {
     531             :         if (__engaged)
     532             :           _M_construct(std::move(__other._M_get()));
     533             :       }
     534             : 
     535             :       _Optional_payload(const _Optional_payload&) = default;
     536             :       _Optional_payload(_Optional_payload&&) = default;
     537             : 
     538             :       constexpr
     539             :       _Optional_payload&
     540             :       operator=(const _Optional_payload& __other)
     541             :       {
     542             :         if (this->_M_engaged && __other._M_engaged)
     543             :           this->_M_get() = __other._M_get();
     544             :         else
     545             :           {
     546             :             if (__other._M_engaged)
     547             :               this->_M_construct(__other._M_get());
     548             :             else
     549             :               this->_M_reset();
     550             :           }
     551             :         return *this;
     552             :       }
     553             : 
     554             :       constexpr
     555             :       _Optional_payload&
     556             :       operator=(_Optional_payload&& __other)
     557             :       noexcept(__and_<is_nothrow_move_constructible<_Tp>,
     558             :                       is_nothrow_move_assignable<_Tp>>())
     559             :       {
     560             :         if (this->_M_engaged && __other._M_engaged)
     561             :           this->_M_get() = std::move(__other._M_get());
     562             :         else
     563             :           {
     564             :             if (__other._M_engaged)
     565             :               this->_M_construct(std::move(__other._M_get()));
     566             :             else
     567             :               this->_M_reset();
     568             :           }
     569             :         return *this;
     570             :       }
     571             : 
     572             :       using _Stored_type = remove_const_t<_Tp>;
     573             : 
     574             :       struct _Empty_byte { };
     575             : 
     576             :       union {
     577             :           _Empty_byte _M_empty;
     578             :           _Stored_type _M_payload;
     579             :       };
     580             :       bool _M_engaged;
     581             : 
     582             :       template<typename... _Args>
     583             :         void
     584             :         _M_construct(_Args&&... __args)
     585             :         noexcept(is_nothrow_constructible<_Stored_type, _Args...>())
     586             :         {
     587             :           ::new ((void *) std::__addressof(this->_M_payload))
     588             :             _Stored_type(std::forward<_Args>(__args)...);
     589             :           this->_M_engaged = true;
     590             :         }
     591             : 
     592             :       // The _M_get operations have _M_engaged as a precondition.
     593             :       constexpr _Tp&
     594             :       _M_get() noexcept
     595             :       { return this->_M_payload; }
     596             : 
     597             :       constexpr const _Tp&
     598             :       _M_get() const noexcept
     599             :       { return this->_M_payload; }
     600             : 
     601             :       // _M_reset is a 'safe' operation with no precondition.
     602             :       constexpr
     603             :       void
     604             :       _M_reset() noexcept
     605             :       {
     606             :         if (this->_M_engaged)
     607             :           {
     608             :             this->_M_engaged = false;
     609             :             this->_M_payload.~_Stored_type();
     610             :           }
     611             :       }
     612             :     };
     613             : 
     614             :   template<typename _Tp, typename _Dp>
     615             :     class _Optional_base_impl
     616             :     {
     617             :     protected:
     618             :       using _Stored_type = remove_const_t<_Tp>;
     619             :       
     620             :       // The _M_construct operation has !_M_engaged as a precondition
     621             :       // while _M_destruct has _M_engaged as a precondition.
     622             :       template<typename... _Args>
     623             :         void
     624             :         _M_construct(_Args&&... __args)
     625             :         noexcept(is_nothrow_constructible<_Stored_type, _Args...>())
     626             :         {
     627             :           ::new
     628             :             (std::__addressof(static_cast<_Dp*>(this)->_M_payload._M_payload))
     629             :             _Stored_type(std::forward<_Args>(__args)...);
     630             :           static_cast<_Dp*>(this)->_M_payload._M_engaged = true;
     631             :         }
     632             :       
     633             :       void
     634             :       _M_destruct() noexcept
     635             :       {
     636             :         static_cast<_Dp*>(this)->_M_payload._M_engaged = false;
     637             :         static_cast<_Dp*>(this)->_M_payload._M_payload.~_Stored_type();
     638             :       }
     639             :       
     640             :       // _M_reset is a 'safe' operation with no precondition.
     641             :       constexpr
     642             :       void
     643             :       _M_reset() noexcept
     644             :       {
     645             :         if (static_cast<_Dp*>(this)->_M_payload._M_engaged)
     646             :           static_cast<_Dp*>(this)->_M_destruct();
     647             :       }
     648             :   };
     649             : 
     650             :   /**
     651             :     * @brief Class template that takes care of copy/move constructors
     652             :     of optional
     653             :     *
     654             :     * Such a separate base class template is necessary in order to
     655             :     * conditionally make copy/move constructors trivial.
     656             :     * @see optional, _Enable_special_members
     657             :     */
     658             :   template<typename _Tp,
     659             :            bool = is_trivially_copy_constructible_v<_Tp>,
     660             :            bool = is_trivially_move_constructible_v<_Tp>>
     661             :     class _Optional_base
     662             :     // protected inheritance because optional needs to reach that base too
     663             :       : protected _Optional_base_impl<_Tp, _Optional_base<_Tp>>
     664             :     {
     665             :       friend class _Optional_base_impl<_Tp, _Optional_base<_Tp>>;
     666             : 
     667             :     public:
     668             :       // Constructors for disengaged optionals.
     669             :       constexpr _Optional_base() = default;
     670             : 
     671             :       // Constructors for engaged optionals.
     672             :       template<typename... _Args,
     673             :                enable_if_t<is_constructible_v<_Tp, _Args&&...>, bool> = false>
     674         176 :         constexpr explicit _Optional_base(in_place_t, _Args&&... __args)
     675             :         : _M_payload(in_place,
     676         176 :                      std::forward<_Args>(__args)...) { }
     677             : 
     678             :       template<typename _Up, typename... _Args,
     679             :                enable_if_t<is_constructible_v<_Tp,
     680             :                                               initializer_list<_Up>&,
     681             :                                               _Args&&...>, bool> = false>
     682             :         constexpr explicit _Optional_base(in_place_t,
     683             :                                           initializer_list<_Up> __il,
     684             :                                           _Args&&... __args)
     685             :         : _M_payload(in_place,
     686             :                      __il, std::forward<_Args>(__args)...)
     687             :         { }
     688             : 
     689             :       // Copy and move constructors.
     690             :       constexpr _Optional_base(const _Optional_base& __other)
     691             :         : _M_payload(__other._M_payload._M_engaged,
     692             :                      __other._M_payload)
     693             :       { }
     694             : 
     695             :       constexpr _Optional_base(_Optional_base&& __other)
     696             :       noexcept(is_nothrow_move_constructible<_Tp>())
     697             :         : _M_payload(__other._M_payload._M_engaged,
     698             :                      std::move(__other._M_payload))
     699             :       { }
     700             : 
     701             :       // Assignment operators.
     702             :       _Optional_base& operator=(const _Optional_base&) = default;
     703             :       _Optional_base& operator=(_Optional_base&&) = default;
     704             : 
     705             :     protected:
     706             : 
     707             :       constexpr bool _M_is_engaged() const noexcept
     708             :       { return this->_M_payload._M_engaged; }
     709             : 
     710             :       // The _M_get operations have _M_engaged as a precondition.
     711             :       constexpr _Tp&
     712           0 :         _M_get() noexcept
     713             :       {
     714             :         __glibcxx_assert(this->_M_is_engaged());
     715           0 :         return this->_M_payload._M_payload;
     716             :       }
     717             : 
     718             :       constexpr const _Tp&
     719             :         _M_get() const noexcept
     720             :       {
     721             :         __glibcxx_assert(this->_M_is_engaged());
     722             :         return this->_M_payload._M_payload;
     723             :       }
     724             : 
     725             :     private:
     726             :       _Optional_payload<_Tp> _M_payload;
     727             :     };
     728             : 
     729             :   template<typename _Tp>
     730             :     class _Optional_base<_Tp, false, true>
     731             :       : protected _Optional_base_impl<_Tp, _Optional_base<_Tp>>
     732             :     {
     733             :       friend class _Optional_base_impl<_Tp, _Optional_base<_Tp>>;
     734             :     public:
     735             : 
     736             :       // Constructors for disengaged optionals.
     737             :       constexpr _Optional_base() = default;
     738             : 
     739             :       // Constructors for engaged optionals.
     740             :       template<typename... _Args,
     741             :                enable_if_t<is_constructible_v<_Tp, _Args&&...>, bool> = false>
     742             :         constexpr explicit _Optional_base(in_place_t, _Args&&... __args)
     743             :         : _M_payload(in_place,
     744             :                      std::forward<_Args>(__args)...) { }
     745             : 
     746             :       template<typename _Up, typename... _Args,
     747             :                enable_if_t<is_constructible_v<_Tp,
     748             :                                               initializer_list<_Up>&,
     749             :                                               _Args&&...>, bool> = false>
     750             :         constexpr explicit _Optional_base(in_place_t,
     751             :                                           initializer_list<_Up> __il,
     752             :                                           _Args&&... __args)
     753             :         : _M_payload(in_place,
     754             :                      __il, std::forward<_Args>(__args)...)
     755             :         { }
     756             : 
     757             :       // Copy and move constructors.
     758             :       constexpr _Optional_base(const _Optional_base& __other)
     759             :         : _M_payload(__other._M_payload._M_engaged,
     760             :                      __other._M_payload)
     761             :       { }
     762             : 
     763             :       constexpr _Optional_base(_Optional_base&& __other) = default;
     764             : 
     765             :       // Assignment operators.
     766             :       _Optional_base& operator=(const _Optional_base&) = default;
     767             :       _Optional_base& operator=(_Optional_base&&) = default;
     768             : 
     769             :     protected:
     770             : 
     771             :       constexpr bool _M_is_engaged() const noexcept
     772             :       { return this->_M_payload._M_engaged; }
     773             : 
     774             :       // The _M_get operations have _M_engaged as a precondition.
     775             :       constexpr _Tp&
     776             :         _M_get() noexcept
     777             :       {
     778             :         __glibcxx_assert(this->_M_is_engaged());
     779             :         return this->_M_payload._M_payload;
     780             :       }
     781             : 
     782             :       constexpr const _Tp&
     783             :         _M_get() const noexcept
     784             :       {
     785             :         __glibcxx_assert(this->_M_is_engaged());
     786             :         return this->_M_payload._M_payload;
     787             :       }
     788             : 
     789             :     private:
     790             :       _Optional_payload<_Tp> _M_payload;
     791             :     };
     792             : 
     793             :   template<typename _Tp>
     794             :     class _Optional_base<_Tp, true, false>
     795             :       : protected _Optional_base_impl<_Tp, _Optional_base<_Tp>>
     796             :     {
     797             :       friend class _Optional_base_impl<_Tp, _Optional_base<_Tp>>;
     798             :     public:
     799             : 
     800             :       // Constructors for disengaged optionals.
     801             :       constexpr _Optional_base() = default;
     802             : 
     803             :       // Constructors for engaged optionals.
     804             :       template<typename... _Args,
     805             :                enable_if_t<is_constructible_v<_Tp, _Args&&...>, bool> = false>
     806             :         constexpr explicit _Optional_base(in_place_t, _Args&&... __args)
     807             :         : _M_payload(in_place,
     808             :                      std::forward<_Args>(__args)...) { }
     809             : 
     810             :       template<typename _Up, typename... _Args,
     811             :                enable_if_t<is_constructible_v<_Tp,
     812             :                                               initializer_list<_Up>&,
     813             :                                               _Args&&...>, bool> = false>
     814             :         constexpr explicit _Optional_base(in_place_t,
     815             :                                           initializer_list<_Up> __il,
     816             :                                           _Args&&... __args)
     817             :         : _M_payload(in_place,
     818             :                      __il, std::forward<_Args>(__args)...)
     819             :         { }
     820             : 
     821             :       // Copy and move constructors.
     822             :       constexpr _Optional_base(const _Optional_base& __other) = default;
     823             : 
     824             :       constexpr _Optional_base(_Optional_base&& __other)
     825             :       noexcept(is_nothrow_move_constructible<_Tp>())
     826             :         : _M_payload(__other._M_payload._M_engaged,
     827             :                      std::move(__other._M_payload))
     828             :       { }
     829             : 
     830             :       // Assignment operators.
     831             :       _Optional_base& operator=(const _Optional_base&) = default;
     832             :       _Optional_base& operator=(_Optional_base&&) = default;
     833             : 
     834             :     protected:
     835             : 
     836             :       constexpr bool _M_is_engaged() const noexcept
     837             :       { return this->_M_payload._M_engaged; }
     838             : 
     839             :       // The _M_get operations have _M_engaged as a precondition.
     840             :       constexpr _Tp&
     841             :         _M_get() noexcept
     842             :       {
     843             :         __glibcxx_assert(this->_M_is_engaged());
     844             :         return this->_M_payload._M_payload;
     845             :       }
     846             : 
     847             :       constexpr const _Tp&
     848             :         _M_get() const noexcept
     849             :       {
     850             :         __glibcxx_assert(this->_M_is_engaged());
     851             :         return this->_M_payload._M_payload;
     852             :       }
     853             : 
     854             :     private:
     855             :       _Optional_payload<_Tp> _M_payload;
     856             :     };
     857             : 
     858             :   template<typename _Tp>
     859             :     class _Optional_base<_Tp, true, true>
     860             :       : protected _Optional_base_impl<_Tp, _Optional_base<_Tp>>
     861             :     {
     862             :       friend class _Optional_base_impl<_Tp, _Optional_base<_Tp>>;
     863             :     public:
     864             : 
     865             :       // Constructors for disengaged optionals.
     866             :       constexpr _Optional_base() = default;
     867             : 
     868             :       // Constructors for engaged optionals.
     869             :       template<typename... _Args,
     870             :                enable_if_t<is_constructible_v<_Tp, _Args&&...>, bool> = false>
     871             :         constexpr explicit _Optional_base(in_place_t, _Args&&... __args)
     872             :         : _M_payload(in_place,
     873             :                      std::forward<_Args>(__args)...) { }
     874             : 
     875             :       template<typename _Up, typename... _Args,
     876             :                enable_if_t<is_constructible_v<_Tp,
     877             :                                               initializer_list<_Up>&,
     878             :                                               _Args&&...>, bool> = false>
     879             :         constexpr explicit _Optional_base(in_place_t,
     880             :                                           initializer_list<_Up> __il,
     881             :                                           _Args&&... __args)
     882             :         : _M_payload(in_place,
     883             :                      __il, std::forward<_Args>(__args)...)
     884             :         { }
     885             : 
     886             :       // Copy and move constructors.
     887             :       constexpr _Optional_base(const _Optional_base& __other) = default;
     888             :       constexpr _Optional_base(_Optional_base&& __other) = default;
     889             : 
     890             :       // Assignment operators.
     891             :       _Optional_base& operator=(const _Optional_base&) = default;
     892             :       _Optional_base& operator=(_Optional_base&&) = default;
     893             : 
     894             :     protected:
     895             : 
     896             :       constexpr bool _M_is_engaged() const noexcept
     897             :       { return this->_M_payload._M_engaged; }
     898             : 
     899             :       // The _M_get operations have _M_engaged as a precondition.
     900             :       constexpr _Tp&
     901             :         _M_get() noexcept
     902             :       {
     903             :         __glibcxx_assert(this->_M_is_engaged());
     904             :         return this->_M_payload._M_payload;
     905             :       }
     906             : 
     907             :       constexpr const _Tp&
     908             :         _M_get() const noexcept
     909             :       {
     910             :         __glibcxx_assert(this->_M_is_engaged());
     911             :         return this->_M_payload._M_payload;
     912             :       }
     913             : 
     914             :     private:
     915             :       _Optional_payload<_Tp> _M_payload;
     916             :     };
     917             : 
     918             :   template<typename _Tp>
     919             :   class optional;
     920             : 
     921             :   template<typename _Tp, typename _Up>
     922             :     using __converts_from_optional =
     923             :       __or_<is_constructible<_Tp, const optional<_Up>&>,
     924             :             is_constructible<_Tp, optional<_Up>&>,
     925             :             is_constructible<_Tp, const optional<_Up>&&>,
     926             :             is_constructible<_Tp, optional<_Up>&&>,
     927             :             is_convertible<const optional<_Up>&, _Tp>,
     928             :             is_convertible<optional<_Up>&, _Tp>,
     929             :             is_convertible<const optional<_Up>&&, _Tp>,
     930             :             is_convertible<optional<_Up>&&, _Tp>>;
     931             : 
     932             :   template<typename _Tp, typename _Up>
     933             :     using __assigns_from_optional =
     934             :       __or_<is_assignable<_Tp&, const optional<_Up>&>,
     935             :             is_assignable<_Tp&, optional<_Up>&>,
     936             :             is_assignable<_Tp&, const optional<_Up>&&>,
     937             :             is_assignable<_Tp&, optional<_Up>&&>>;
     938             : 
     939             :   /**
     940             :     * @brief Class template for optional values.
     941             :     */
     942             :   template<typename _Tp>
     943             :     class optional
     944             :     : private _Optional_base<_Tp>,
     945             :       private _Enable_copy_move<
     946             :         // Copy constructor.
     947             :         is_copy_constructible<_Tp>::value,
     948             :         // Copy assignment.
     949             :         __and_<is_copy_constructible<_Tp>, is_copy_assignable<_Tp>>::value,
     950             :         // Move constructor.
     951             :         is_move_constructible<_Tp>::value,
     952             :         // Move assignment.
     953             :         __and_<is_move_constructible<_Tp>, is_move_assignable<_Tp>>::value,
     954             :         // Unique tag type.
     955             :         optional<_Tp>>
     956             :     {
     957             :       static_assert(!is_same_v<remove_cv_t<_Tp>, nullopt_t>);
     958             :       static_assert(!is_same_v<remove_cv_t<_Tp>, in_place_t>);
     959             :       static_assert(!is_reference_v<_Tp>);
     960             : 
     961             :     private:
     962             :       using _Base = _Optional_base<_Tp>;
     963             : 
     964             :     public:
     965             :       using value_type = _Tp;
     966             : 
     967             :       constexpr optional() = default;
     968             : 
     969             :       constexpr optional(nullopt_t) noexcept { }
     970             : 
     971             :       // Converting constructors for engaged optionals.
     972             :       template <typename _Up = _Tp,
     973             :                 enable_if_t<__and_<
     974             :                               __not_<is_same<optional<_Tp>, decay_t<_Up>>>,
     975             :                               __not_<is_same<in_place_t, decay_t<_Up>>>,
     976             :                               is_constructible<_Tp, _Up&&>,
     977             :                               is_convertible<_Up&&, _Tp>
     978             :                               >::value, bool> = true>
     979         176 :       constexpr optional(_Up&& __t)
     980         176 :         : _Base(std::in_place, std::forward<_Up>(__t)) { }
     981             : 
     982             :       template <typename _Up = _Tp,
     983             :                 enable_if_t<__and_<
     984             :                               __not_<is_same<optional<_Tp>, decay_t<_Up>>>,
     985             :                               __not_<is_same<in_place_t, decay_t<_Up>>>,
     986             :                               is_constructible<_Tp, _Up&&>,
     987             :                               __not_<is_convertible<_Up&&, _Tp>>
     988             :                               >::value, bool> = false>
     989             :       explicit constexpr optional(_Up&& __t)
     990             :         : _Base(std::in_place, std::forward<_Up>(__t)) { }
     991             : 
     992             :       template <typename _Up,
     993             :                 enable_if_t<__and_<
     994             :                             __not_<is_same<_Tp, _Up>>,
     995             :                             is_constructible<_Tp, const _Up&>,
     996             :                             is_convertible<const _Up&, _Tp>,
     997             :                             __not_<__converts_from_optional<_Tp, _Up>>
     998             :                             >::value, bool> = true>
     999             :       constexpr optional(const optional<_Up>& __t)
    1000             :       {
    1001             :         if (__t)
    1002             :           emplace(*__t);
    1003             :       }
    1004             : 
    1005             :       template <typename _Up,
    1006             :                  enable_if_t<__and_<
    1007             :                                __not_<is_same<_Tp, _Up>>,
    1008             :                                is_constructible<_Tp, const _Up&>,
    1009             :                                __not_<is_convertible<const _Up&, _Tp>>,
    1010             :                                __not_<__converts_from_optional<_Tp, _Up>>
    1011             :                                >::value, bool> = false>
    1012             :       explicit constexpr optional(const optional<_Up>& __t)
    1013             :       {
    1014             :         if (__t)
    1015             :           emplace(*__t);
    1016             :       }
    1017             : 
    1018             :       template <typename _Up,
    1019             :                 enable_if_t<__and_<
    1020             :                               __not_<is_same<_Tp, _Up>>,
    1021             :                               is_constructible<_Tp, _Up&&>,
    1022             :                               is_convertible<_Up&&, _Tp>,
    1023             :                               __not_<__converts_from_optional<_Tp, _Up>>
    1024             :                               >::value, bool> = true>
    1025             :       constexpr optional(optional<_Up>&& __t)
    1026             :       {
    1027             :         if (__t)
    1028             :           emplace(std::move(*__t));
    1029             :       }
    1030             : 
    1031             :       template <typename _Up,
    1032             :                 enable_if_t<__and_<
    1033             :                             __not_<is_same<_Tp, _Up>>,
    1034             :                             is_constructible<_Tp, _Up&&>,
    1035             :                             __not_<is_convertible<_Up&&, _Tp>>,
    1036             :                             __not_<__converts_from_optional<_Tp, _Up>>
    1037             :                             >::value, bool> = false>
    1038             :       explicit constexpr optional(optional<_Up>&& __t)
    1039             :       {
    1040             :         if (__t)
    1041             :           emplace(std::move(*__t));
    1042             :       }
    1043             : 
    1044             :       template<typename... _Args,
    1045             :                enable_if_t<is_constructible_v<_Tp, _Args&&...>, bool> = false>
    1046             :       explicit constexpr optional(in_place_t, _Args&&... __args)
    1047             :         : _Base(std::in_place, std::forward<_Args>(__args)...) { }
    1048             : 
    1049             :       template<typename _Up, typename... _Args,
    1050             :                enable_if_t<is_constructible_v<_Tp,
    1051             :                                               initializer_list<_Up>&,
    1052             :                                               _Args&&...>, bool> = false>
    1053             :       explicit constexpr optional(in_place_t,
    1054             :                                   initializer_list<_Up> __il,
    1055             :                                   _Args&&... __args)
    1056             :         : _Base(std::in_place, __il, std::forward<_Args>(__args)...) { }
    1057             : 
    1058             :       // Assignment operators.
    1059             :       optional&
    1060             :       operator=(nullopt_t) noexcept
    1061             :       {
    1062             :         this->_M_reset();
    1063             :         return *this;
    1064             :       }
    1065             : 
    1066             :       template<typename _Up = _Tp>
    1067             :         enable_if_t<__and_<
    1068             :                       __not_<is_same<optional<_Tp>, decay_t<_Up>>>,
    1069             :                       is_constructible<_Tp, _Up>,
    1070             :                       __not_<__and_<is_scalar<_Tp>,
    1071             :                                     is_same<_Tp, decay_t<_Up>>>>,
    1072             :                       is_assignable<_Tp&, _Up>>::value,
    1073             :                     optional&>
    1074             :         operator=(_Up&& __u)
    1075             :         {
    1076             :           if (this->_M_is_engaged())
    1077             :             this->_M_get() = std::forward<_Up>(__u);
    1078             :           else
    1079             :             this->_M_construct(std::forward<_Up>(__u));
    1080             : 
    1081             :           return *this;
    1082             :         }
    1083             : 
    1084             :       template<typename _Up>
    1085             :         enable_if_t<__and_<
    1086             :                       __not_<is_same<_Tp, _Up>>,
    1087             :                       is_constructible<_Tp, const _Up&>,
    1088             :                       is_assignable<_Tp&, _Up>,
    1089             :                       __not_<__converts_from_optional<_Tp, _Up>>,
    1090             :                       __not_<__assigns_from_optional<_Tp, _Up>>
    1091             :                       >::value,
    1092             :                     optional&>
    1093             :         operator=(const optional<_Up>& __u)
    1094             :         {
    1095             :           if (__u)
    1096             :             {
    1097             :               if (this->_M_is_engaged())
    1098             :                 this->_M_get() = *__u;
    1099             :               else
    1100             :                 this->_M_construct(*__u);
    1101             :             }
    1102             :           else
    1103             :             {
    1104             :               this->_M_reset();
    1105             :             }
    1106             :           return *this;
    1107             :         }
    1108             : 
    1109             :       template<typename _Up>
    1110             :         enable_if_t<__and_<
    1111             :                       __not_<is_same<_Tp, _Up>>,
    1112             :                       is_constructible<_Tp, _Up>,
    1113             :                       is_assignable<_Tp&, _Up>,
    1114             :                       __not_<__converts_from_optional<_Tp, _Up>>,
    1115             :                       __not_<__assigns_from_optional<_Tp, _Up>>
    1116             :                       >::value,
    1117             :                     optional&>
    1118             :         operator=(optional<_Up>&& __u)
    1119             :         {
    1120             :           if (__u)
    1121             :             {
    1122             :               if (this->_M_is_engaged())
    1123             :                 this->_M_get() = std::move(*__u);
    1124             :               else
    1125             :                 this->_M_construct(std::move(*__u));
    1126             :             }
    1127             :           else
    1128             :             {
    1129             :               this->_M_reset();
    1130             :             }
    1131             : 
    1132             :           return *this;
    1133             :         }
    1134             : 
    1135             :       template<typename... _Args>
    1136             :         enable_if_t<is_constructible<_Tp, _Args&&...>::value, _Tp&>
    1137             :         emplace(_Args&&... __args)
    1138             :         {
    1139             :           this->_M_reset();
    1140             :           this->_M_construct(std::forward<_Args>(__args)...);
    1141             :           return this->_M_get();
    1142             :         }
    1143             : 
    1144             :       template<typename _Up, typename... _Args>
    1145             :         enable_if_t<is_constructible<_Tp, initializer_list<_Up>&,
    1146             :                                      _Args&&...>::value, _Tp&>
    1147             :         emplace(initializer_list<_Up> __il, _Args&&... __args)
    1148             :         {
    1149             :           this->_M_reset();
    1150             :           this->_M_construct(__il, std::forward<_Args>(__args)...);
    1151             :           return this->_M_get();
    1152             :         }
    1153             : 
    1154             :       // Destructor is implicit, implemented in _Optional_base.
    1155             : 
    1156             :       // Swap.
    1157             :       void
    1158             :       swap(optional& __other)
    1159             :       noexcept(is_nothrow_move_constructible<_Tp>()
    1160             :                && is_nothrow_swappable_v<_Tp>)
    1161             :       {
    1162             :         using std::swap;
    1163             : 
    1164             :         if (this->_M_is_engaged() && __other._M_is_engaged())
    1165             :           swap(this->_M_get(), __other._M_get());
    1166             :         else if (this->_M_is_engaged())
    1167             :           {
    1168             :             __other._M_construct(std::move(this->_M_get()));
    1169             :             this->_M_destruct();
    1170             :           }
    1171             :         else if (__other._M_is_engaged())
    1172             :           {
    1173             :             this->_M_construct(std::move(__other._M_get()));
    1174             :             __other._M_destruct();
    1175             :           }
    1176             :       }
    1177             : 
    1178             :       // Observers.
    1179             :       constexpr const _Tp*
    1180             :       operator->() const
    1181             :       { return std::__addressof(this->_M_get()); }
    1182             : 
    1183             :       constexpr
    1184             :       _Tp*
    1185             :       operator->()
    1186             :       { return std::__addressof(this->_M_get()); }
    1187             : 
    1188             :       constexpr const _Tp&
    1189             :       operator*() const&
    1190             :       { return this->_M_get(); }
    1191             : 
    1192             :       constexpr _Tp&
    1193           0 :       operator*()&
    1194           0 :       { return this->_M_get(); }
    1195             : 
    1196             :       constexpr _Tp&&
    1197             :       operator*()&&
    1198             :       { return std::move(this->_M_get()); }
    1199             : 
    1200             :       constexpr const _Tp&&
    1201             :       operator*() const&&
    1202             :       { return std::move(this->_M_get()); }
    1203             : 
    1204             :       constexpr explicit operator bool() const noexcept
    1205             :       { return this->_M_is_engaged(); }
    1206             : 
    1207             :       constexpr bool has_value() const noexcept
    1208             :       { return this->_M_is_engaged(); }
    1209             : 
    1210             :       constexpr const _Tp&
    1211             :       value() const&
    1212             :       {
    1213             :         return this->_M_is_engaged()
    1214             :           ?  this->_M_get()
    1215             :           : (__throw_bad_optional_access(),
    1216             :              this->_M_get());
    1217             :       }
    1218             : 
    1219             :       constexpr _Tp&
    1220             :       value()&
    1221             :       {
    1222             :         return this->_M_is_engaged()
    1223             :           ?  this->_M_get()
    1224             :           : (__throw_bad_optional_access(),
    1225             :              this->_M_get());
    1226             :       }
    1227             : 
    1228             :       constexpr _Tp&&
    1229             :       value()&&
    1230             :       {
    1231             :         return this->_M_is_engaged()
    1232             :           ?  std::move(this->_M_get())
    1233             :           : (__throw_bad_optional_access(),
    1234             :              std::move(this->_M_get()));
    1235             :       }
    1236             : 
    1237             :       constexpr const _Tp&&
    1238             :       value() const&&
    1239             :       {
    1240             :         return this->_M_is_engaged()
    1241             :           ?  std::move(this->_M_get())
    1242             :           : (__throw_bad_optional_access(),
    1243             :              std::move(this->_M_get()));
    1244             :       }
    1245             : 
    1246             :       template<typename _Up>
    1247             :         constexpr _Tp
    1248             :         value_or(_Up&& __u) const&
    1249             :         {
    1250             :           static_assert(is_copy_constructible_v<_Tp>);
    1251             :           static_assert(is_convertible_v<_Up&&, _Tp>);
    1252             : 
    1253             :           return this->_M_is_engaged()
    1254             :             ? this->_M_get()
    1255             :             : static_cast<_Tp>(std::forward<_Up>(__u));
    1256             :         }
    1257             : 
    1258             :       template<typename _Up>
    1259             :         constexpr _Tp
    1260             :         value_or(_Up&& __u) &&
    1261             :         {
    1262             :           static_assert(is_move_constructible_v<_Tp>);
    1263             :           static_assert(is_convertible_v<_Up&&, _Tp>);
    1264             : 
    1265             :           return this->_M_is_engaged()
    1266             :             ? std::move(this->_M_get())
    1267             :             : static_cast<_Tp>(std::forward<_Up>(__u));
    1268             :         }
    1269             :       void reset() noexcept { this->_M_reset(); }
    1270             :     };
    1271             : 
    1272             :   template<typename _Tp>
    1273             :     using __optional_relop_t =
    1274             :     enable_if_t<is_convertible<_Tp, bool>::value, bool>;
    1275             : 
    1276             :   // Comparisons between optional values.
    1277             :   template<typename _Tp, typename _Up>
    1278             :     constexpr auto
    1279             :     operator==(const optional<_Tp>& __lhs, const optional<_Up>& __rhs)
    1280             :     -> __optional_relop_t<decltype(declval<_Tp>() == declval<_Up>())>
    1281             :     {
    1282             :       return static_cast<bool>(__lhs) == static_cast<bool>(__rhs)
    1283             :              && (!__lhs || *__lhs == *__rhs);
    1284             :     }
    1285             : 
    1286             :   template<typename _Tp, typename _Up>
    1287             :     constexpr auto
    1288             :     operator!=(const optional<_Tp>& __lhs, const optional<_Up>& __rhs)
    1289             :     -> __optional_relop_t<decltype(declval<_Tp>() != declval<_Up>())>
    1290             :     {
    1291             :       return static_cast<bool>(__lhs) != static_cast<bool>(__rhs)
    1292             :         || (static_cast<bool>(__lhs) && *__lhs != *__rhs);
    1293             :     }
    1294             : 
    1295             :   template<typename _Tp, typename _Up>
    1296             :     constexpr auto
    1297             :     operator<(const optional<_Tp>& __lhs, const optional<_Up>& __rhs)
    1298             :     -> __optional_relop_t<decltype(declval<_Tp>() < declval<_Up>())>
    1299             :     {
    1300             :       return static_cast<bool>(__rhs) && (!__lhs || *__lhs < *__rhs);
    1301             :     }
    1302             : 
    1303             :   template<typename _Tp, typename _Up>
    1304             :     constexpr auto
    1305             :     operator>(const optional<_Tp>& __lhs, const optional<_Up>& __rhs)
    1306             :     -> __optional_relop_t<decltype(declval<_Tp>() > declval<_Up>())>
    1307             :     {
    1308             :       return static_cast<bool>(__lhs) && (!__rhs || *__lhs > *__rhs);
    1309             :     }
    1310             : 
    1311             :   template<typename _Tp, typename _Up>
    1312             :     constexpr auto
    1313             :     operator<=(const optional<_Tp>& __lhs, const optional<_Up>& __rhs)
    1314             :     -> __optional_relop_t<decltype(declval<_Tp>() <= declval<_Up>())>
    1315             :     {
    1316             :       return !__lhs || (static_cast<bool>(__rhs) && *__lhs <= *__rhs);
    1317             :     }
    1318             : 
    1319             :   template<typename _Tp, typename _Up>
    1320             :     constexpr auto
    1321             :     operator>=(const optional<_Tp>& __lhs, const optional<_Up>& __rhs)
    1322             :     -> __optional_relop_t<decltype(declval<_Tp>() >= declval<_Up>())>
    1323             :     {
    1324             :       return !__rhs || (static_cast<bool>(__lhs) && *__lhs >= *__rhs);
    1325             :     }
    1326             : 
    1327             :   // Comparisons with nullopt.
    1328             :   template<typename _Tp>
    1329             :     constexpr bool
    1330             :     operator==(const optional<_Tp>& __lhs, nullopt_t) noexcept
    1331             :     { return !__lhs; }
    1332             : 
    1333             :   template<typename _Tp>
    1334             :     constexpr bool
    1335             :     operator==(nullopt_t, const optional<_Tp>& __rhs) noexcept
    1336             :     { return !__rhs; }
    1337             : 
    1338             :   template<typename _Tp>
    1339             :     constexpr bool
    1340             :     operator!=(const optional<_Tp>& __lhs, nullopt_t) noexcept
    1341             :     { return static_cast<bool>(__lhs); }
    1342             : 
    1343             :   template<typename _Tp>
    1344             :     constexpr bool
    1345             :     operator!=(nullopt_t, const optional<_Tp>& __rhs) noexcept
    1346             :     { return static_cast<bool>(__rhs); }
    1347             : 
    1348             :   template<typename _Tp>
    1349             :     constexpr bool
    1350             :     operator<(const optional<_Tp>& /* __lhs */, nullopt_t) noexcept
    1351             :     { return false; }
    1352             : 
    1353             :   template<typename _Tp>
    1354             :     constexpr bool
    1355             :     operator<(nullopt_t, const optional<_Tp>& __rhs) noexcept
    1356             :     { return static_cast<bool>(__rhs); }
    1357             : 
    1358             :   template<typename _Tp>
    1359             :     constexpr bool
    1360             :     operator>(const optional<_Tp>& __lhs, nullopt_t) noexcept
    1361             :     { return static_cast<bool>(__lhs); }
    1362             : 
    1363             :   template<typename _Tp>
    1364             :     constexpr bool
    1365             :     operator>(nullopt_t, const optional<_Tp>& /* __rhs */) noexcept
    1366             :     { return false; }
    1367             : 
    1368             :   template<typename _Tp>
    1369             :     constexpr bool
    1370             :     operator<=(const optional<_Tp>& __lhs, nullopt_t) noexcept
    1371             :     { return !__lhs; }
    1372             : 
    1373             :   template<typename _Tp>
    1374             :     constexpr bool
    1375             :     operator<=(nullopt_t, const optional<_Tp>& /* __rhs */) noexcept
    1376             :     { return true; }
    1377             : 
    1378             :   template<typename _Tp>
    1379             :     constexpr bool
    1380             :     operator>=(const optional<_Tp>& /* __lhs */, nullopt_t) noexcept
    1381             :     { return true; }
    1382             : 
    1383             :   template<typename _Tp>
    1384             :     constexpr bool
    1385             :     operator>=(nullopt_t, const optional<_Tp>& __rhs) noexcept
    1386             :     { return !__rhs; }
    1387             : 
    1388             :   // Comparisons with value type.
    1389             :   template<typename _Tp, typename _Up>
    1390             :     constexpr auto
    1391             :     operator==(const optional<_Tp>& __lhs, const _Up& __rhs)
    1392             :     -> __optional_relop_t<decltype(declval<_Tp>() == declval<_Up>())>
    1393             :     { return __lhs && *__lhs == __rhs; }
    1394             : 
    1395             :   template<typename _Tp, typename _Up>
    1396             :     constexpr auto
    1397             :     operator==(const _Up& __lhs, const optional<_Tp>& __rhs)
    1398             :     -> __optional_relop_t<decltype(declval<_Up>() == declval<_Tp>())>
    1399             :     { return __rhs && __lhs == *__rhs; }
    1400             : 
    1401             :   template<typename _Tp, typename _Up>
    1402             :     constexpr auto
    1403             :     operator!=(const optional<_Tp>& __lhs, const _Up& __rhs)
    1404             :     -> __optional_relop_t<decltype(declval<_Tp>() != declval<_Up>())>
    1405             :     { return !__lhs || *__lhs != __rhs; }
    1406             : 
    1407             :   template<typename _Tp, typename _Up>
    1408             :     constexpr auto
    1409             :     operator!=(const _Up& __lhs, const optional<_Tp>& __rhs)
    1410             :     -> __optional_relop_t<decltype(declval<_Up>() != declval<_Tp>())>
    1411             :     { return !__rhs || __lhs != *__rhs; }
    1412             : 
    1413             :   template<typename _Tp, typename _Up>
    1414             :     constexpr auto
    1415             :     operator<(const optional<_Tp>& __lhs, const _Up& __rhs)
    1416             :     -> __optional_relop_t<decltype(declval<_Tp>() < declval<_Up>())>
    1417             :     { return !__lhs || *__lhs < __rhs; }
    1418             : 
    1419             :   template<typename _Tp, typename _Up>
    1420             :     constexpr auto
    1421             :     operator<(const _Up& __lhs, const optional<_Tp>& __rhs)
    1422             :     -> __optional_relop_t<decltype(declval<_Up>() < declval<_Tp>())>
    1423             :     { return __rhs && __lhs < *__rhs; }
    1424             : 
    1425             :   template<typename _Tp, typename _Up>
    1426             :     constexpr auto
    1427             :     operator>(const optional<_Tp>& __lhs, const _Up& __rhs)
    1428             :     -> __optional_relop_t<decltype(declval<_Tp>() > declval<_Up>())>
    1429             :     { return __lhs && *__lhs > __rhs; }
    1430             : 
    1431             :   template<typename _Tp, typename _Up>
    1432             :     constexpr auto
    1433             :     operator>(const _Up& __lhs, const optional<_Tp>& __rhs)
    1434             :     -> __optional_relop_t<decltype(declval<_Up>() > declval<_Tp>())>
    1435             :     { return !__rhs || __lhs > *__rhs; }
    1436             : 
    1437             :   template<typename _Tp, typename _Up>
    1438             :     constexpr auto
    1439             :     operator<=(const optional<_Tp>& __lhs, const _Up& __rhs)
    1440             :     -> __optional_relop_t<decltype(declval<_Tp>() <= declval<_Up>())>
    1441             :     { return !__lhs || *__lhs <= __rhs; }
    1442             : 
    1443             :   template<typename _Tp, typename _Up>
    1444             :     constexpr auto
    1445             :     operator<=(const _Up& __lhs, const optional<_Tp>& __rhs)
    1446             :     -> __optional_relop_t<decltype(declval<_Up>() <= declval<_Tp>())>
    1447             :     { return __rhs && __lhs <= *__rhs; }
    1448             : 
    1449             :   template<typename _Tp, typename _Up>
    1450             :     constexpr auto
    1451             :     operator>=(const optional<_Tp>& __lhs, const _Up& __rhs)
    1452             :     -> __optional_relop_t<decltype(declval<_Tp>() >= declval<_Up>())>
    1453             :     { return __lhs && *__lhs >= __rhs; }
    1454             : 
    1455             :   template<typename _Tp, typename _Up>
    1456             :     constexpr auto
    1457             :     operator>=(const _Up& __lhs, const optional<_Tp>& __rhs)
    1458             :     -> __optional_relop_t<decltype(declval<_Up>() >= declval<_Tp>())>
    1459             :     { return !__rhs || __lhs >= *__rhs; }
    1460             : 
    1461             :   // Swap and creation functions.
    1462             : 
    1463             :   // _GLIBCXX_RESOLVE_LIB_DEFECTS
    1464             :   // 2748. swappable traits for optionals
    1465             :   template<typename _Tp>
    1466             :     inline enable_if_t<is_move_constructible_v<_Tp> && is_swappable_v<_Tp>>
    1467             :     swap(optional<_Tp>& __lhs, optional<_Tp>& __rhs)
    1468             :     noexcept(noexcept(__lhs.swap(__rhs)))
    1469             :     { __lhs.swap(__rhs); }
    1470             : 
    1471             :   template<typename _Tp>
    1472             :     enable_if_t<!(is_move_constructible_v<_Tp> && is_swappable_v<_Tp>)>
    1473             :     swap(optional<_Tp>&, optional<_Tp>&) = delete;
    1474             : 
    1475             :   template<typename _Tp>
    1476             :     constexpr optional<decay_t<_Tp>>
    1477             :     make_optional(_Tp&& __t)
    1478             :     { return optional<decay_t<_Tp>> { std::forward<_Tp>(__t) }; }
    1479             : 
    1480             :   template<typename _Tp, typename ..._Args>
    1481             :     constexpr optional<_Tp>
    1482             :     make_optional(_Args&&... __args)
    1483             :     { return optional<_Tp> { in_place, std::forward<_Args>(__args)... }; }
    1484             : 
    1485             :   template<typename _Tp, typename _Up, typename ..._Args>
    1486             :     constexpr optional<_Tp>
    1487             :     make_optional(initializer_list<_Up> __il, _Args&&... __args)
    1488             :     { return optional<_Tp> { in_place, __il, std::forward<_Args>(__args)... }; }
    1489             : 
    1490             :   // Hash.
    1491             : 
    1492             :   template<typename _Tp, typename _Up = remove_const_t<_Tp>,
    1493             :            bool = __poison_hash<_Up>::__enable_hash_call>
    1494             :     struct __optional_hash_call_base
    1495             :     {
    1496             :       size_t
    1497             :       operator()(const optional<_Tp>& __t) const
    1498             :       noexcept(noexcept(hash<_Up>{}(*__t)))
    1499             :       {
    1500             :         // We pick an arbitrary hash for disengaged optionals which hopefully
    1501             :         // usual values of _Tp won't typically hash to.
    1502             :         constexpr size_t __magic_disengaged_hash = static_cast<size_t>(-3333);
    1503             :         return __t ? hash<_Up>{}(*__t) : __magic_disengaged_hash;
    1504             :       }
    1505             :     };
    1506             : 
    1507             :   template<typename _Tp, typename _Up>
    1508             :     struct __optional_hash_call_base<_Tp, _Up, false> {};
    1509             : 
    1510             :   template<typename _Tp>
    1511             :     struct hash<optional<_Tp>>
    1512             :     : private __poison_hash<remove_const_t<_Tp>>,
    1513             :       public __optional_hash_call_base<_Tp>
    1514             :     {
    1515             :       using result_type [[__deprecated__]] = size_t;
    1516             :       using argument_type [[__deprecated__]] = optional<_Tp>;
    1517             :     };
    1518             : 
    1519             :   template<typename _Tp>
    1520             :     struct __is_fast_hash<hash<optional<_Tp>>> : __is_fast_hash<hash<_Tp>>
    1521             :     { };
    1522             : 
    1523             :   /// @}
    1524             : 
    1525             : #if __cpp_deduction_guides >= 201606
    1526             :   template <typename _Tp> optional(_Tp) -> optional<_Tp>;
    1527             : #endif
    1528             : 
    1529             : _GLIBCXX_END_NAMESPACE_VERSION
    1530             : } // namespace std
    1531             : 
    1532             : #endif // C++17
    1533             : 
    1534             : #endif // _GLIBCXX_OPTIONAL

Generated by: LCOV version 1.14