xref: /dragonfly/contrib/gcc-8.0/libstdc++-v3/include/std/optional (revision 95059079af47f9a66a175f374f2da1a5020e3255)
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
45namespace std _GLIBCXX_VISIBILITY(default)
46{
47_GLIBCXX_BEGIN_NAMESPACE_VERSION
48
49  /**
50   *  @addtogroup utilities
51   *  @{
52   */
53
54#define __cpp_lib_optional 201603
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          _Optional_payload(in_place_t, _Args&&... __args)
119          : _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      ~_Optional_payload()
198      {
199        if (_M_engaged)
200          _M_payload.~_Stored_type();
201      }
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        constexpr explicit _Optional_base(in_place_t, _Args&&... __args)
675        : _M_payload(in_place,
676                         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          _M_get() noexcept
713      {
714          __glibcxx_assert(this->_M_is_engaged());
715          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      constexpr optional(_Up&& __t)
980        : _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      operator*()&
1194      { 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          _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
1535