1// <optional> -*- C++ -*-
2
3// Copyright (C) 2013-2014 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 experimental/optional
26 *  This is a TS C++ Library header.
27 */
28
29#ifndef _GLIBCXX_EXPERIMENTAL_OPTIONAL
30#define _GLIBCXX_EXPERIMENTAL_OPTIONAL 1
31
32/**
33 * @defgroup experimental Experimental
34 *
35 * Components specified by various Technical Specifications.
36 */
37
38#if __cplusplus <= 201103L
39# include <bits/c++14_warning.h>
40#else
41
42#include <utility>
43#include <type_traits>
44#include <stdexcept>
45#include <new>
46#include <initializer_list>
47#include <bits/functexcept.h>
48#include <bits/functional_hash.h>
49#include <bits/enable_special_members.h>
50
51namespace std _GLIBCXX_VISIBILITY(default)
52{
53namespace experimental
54{
55_GLIBCXX_BEGIN_NAMESPACE_VERSION
56
57  /**
58   * @defgroup optional Optional values
59   * @ingroup experimental
60   *
61   * Class template for optional values and surrounding facilities, as
62   * described in n3793 "A proposal to add a utility class to represent
63   * optional objects (Revision 5)".
64   *
65   * @{
66   */
67
68  // All subsequent [X.Y.n] references are against n3793.
69
70  // [X.Y.4]
71  template<typename _Tp>
72    class optional;
73
74  // [X.Y.5]
75  /// Tag type for in-place construction.
76  struct in_place_t { };
77
78  /// Tag for in-place construction.
79  constexpr in_place_t in_place { };
80
81  // [X.Y.6]
82  /// Tag type to disengage optional objects.
83  struct nullopt_t
84  {
85    // Do not user-declare default constructor at all for
86    // optional_value = {} syntax to work.
87    // nullopt_t() = delete;
88
89    // Used for constructing nullopt.
90    enum class _Construct { _Token };
91
92    // Must be constexpr for nullopt_t to be literal.
93    explicit constexpr nullopt_t(_Construct) { }
94  };
95
96  // [X.Y.6]
97  /// Tag to disengage optional objects.
98  constexpr nullopt_t nullopt { nullopt_t::_Construct::_Token };
99
100  // [X.Y.7]
101  /**
102   *  @brief Exception class thrown when a disengaged optional object is
103   *  dereferenced.
104   *  @ingroup exceptions
105   */
106  class bad_optional_access : public logic_error
107  {
108  public:
109    bad_optional_access() : logic_error("bad optional access") { }
110
111    // XXX This constructor is non-standard. Should not be inline
112    explicit bad_optional_access(const char* __arg) : logic_error(__arg) { }
113
114    virtual ~bad_optional_access() noexcept = default;
115  };
116
117  void
118  __throw_bad_optional_access(const char*)
119  __attribute__((__noreturn__));
120
121  // XXX Does not belong here.
122  inline void
123  __throw_bad_optional_access(const char* __s)
124  { _GLIBCXX_THROW_OR_ABORT(bad_optional_access(__s)); }
125
126  template<typename _Tp, typename _Sfinae = void>
127    struct _Has_addressof_impl : std::false_type { };
128
129  template<typename _Tp>
130    struct _Has_addressof_impl<_Tp,
131      decltype( std::declval<const _Tp&>().operator&(), void() )>
132      : std::true_type { };
133
134  /**
135    * @brief Trait that detects the presence of an overloaded unary operator&.
136    *
137    * Practically speaking this detects the presence of such an operator when
138    * called on a const-qualified lvalue (i.e.
139    * declval<_Tp * const&>().operator&()).
140    */
141  template<typename _Tp>
142    struct _Has_addressof : _Has_addressof_impl<_Tp>::type { };
143
144  /**
145    * @brief An overload that attempts to take the address of an lvalue as a
146    * constant expression. Falls back to __addressof in the presence of an
147    * overloaded addressof operator (unary operator&), in which case the call
148    * will not be a constant expression.
149    */
150  template<typename _Tp, typename enable_if<!_Has_addressof<_Tp>::value,
151                                            int>::type...>
152    constexpr _Tp* __constexpr_addressof(_Tp& __t)
153    { return &__t; }
154
155  /**
156    * @brief Fallback overload that defers to __addressof.
157    */
158  template<typename _Tp, typename enable_if<_Has_addressof<_Tp>::value,
159                                            int>::type...>
160    inline _Tp* __constexpr_addressof(_Tp& __t)
161    { return std::__addressof(__t); }
162
163  /**
164    * @brief Class template that holds the necessary state for @ref optional
165    * and that has the responsibility for construction and the special members.
166    *
167    * Such a separate base class template is necessary in order to
168    * conditionally enable the special members (e.g. copy/move constructors).
169    * Note that this means that @ref _Optional_base implements the
170    * functionality for copy and move assignment, but not for converting
171    * assignment.
172    *
173    * @see optional, _Enable_special_members
174    */
175  template<typename _Tp, bool _ShouldProvideDestructor =
176	   !is_trivially_destructible<_Tp>::value>
177    class _Optional_base
178    {
179    private:
180      // Remove const to avoid prohibition of reusing object storage for
181      // const-qualified types in [3.8/9]. This is strictly internal
182      // and even optional itself is oblivious to it.
183      using _Stored_type = typename remove_const<_Tp>::type;
184
185    public:
186      // [X.Y.4.1] Constructors.
187
188      // Constructors for disengaged optionals.
189      constexpr _Optional_base() noexcept
190      : _M_empty{} { }
191
192      constexpr _Optional_base(nullopt_t) noexcept
193      : _Optional_base{} { }
194
195      // Constructors for engaged optionals.
196      constexpr _Optional_base(const _Tp& __t)
197      : _M_payload(__t), _M_engaged(true) { }
198
199      constexpr _Optional_base(_Tp&& __t)
200      : _M_payload(std::move(__t)), _M_engaged(true) { }
201
202      template<typename... _Args>
203        constexpr explicit _Optional_base(in_place_t, _Args&&... __args)
204        : _M_payload(std::forward<_Args>(__args)...), _M_engaged(true) { }
205
206      template<typename _Up, typename... _Args,
207               typename enable_if<is_constructible<_Tp,
208                                                   initializer_list<_Up>&,
209                                                   _Args&&...>::value,
210                                  int>::type...>
211        constexpr explicit _Optional_base(in_place_t,
212                                          initializer_list<_Up> __il,
213                                          _Args&&... __args)
214        : _M_payload(__il, std::forward<_Args>(__args)...),
215          _M_engaged(true) { }
216
217      // Copy and move constructors.
218      _Optional_base(const _Optional_base& __other)
219      {
220        if (__other._M_engaged)
221          this->_M_construct(__other._M_get());
222      }
223
224      _Optional_base(_Optional_base&& __other)
225      noexcept(is_nothrow_move_constructible<_Tp>())
226      {
227        if (__other._M_engaged)
228          this->_M_construct(std::move(__other._M_get()));
229      }
230
231      // [X.Y.4.3] (partly) Assignment.
232      _Optional_base&
233      operator=(const _Optional_base& __other)
234      {
235        if (this->_M_engaged && __other._M_engaged)
236          this->_M_get() = __other._M_get();
237        else
238	  {
239	    if (__other._M_engaged)
240	      this->_M_construct(__other._M_get());
241	    else
242	      this->_M_reset();
243	  }
244
245        return *this;
246      }
247
248      _Optional_base&
249      operator=(_Optional_base&& __other)
250      noexcept(__and_<is_nothrow_move_constructible<_Tp>,
251		      is_nothrow_move_assignable<_Tp>>())
252      {
253	if (this->_M_engaged && __other._M_engaged)
254	  this->_M_get() = std::move(__other._M_get());
255	else
256	  {
257	    if (__other._M_engaged)
258	      this->_M_construct(std::move(__other._M_get()));
259	    else
260	      this->_M_reset();
261	  }
262	return *this;
263      }
264
265      // [X.Y.4.2] Destructor.
266      ~_Optional_base()
267      {
268        if (this->_M_engaged)
269          this->_M_payload.~_Stored_type();
270      }
271
272      // The following functionality is also needed by optional, hence the
273      // protected accessibility.
274    protected:
275      constexpr bool _M_is_engaged() const noexcept
276      { return this->_M_engaged; }
277
278      // The _M_get operations have _M_engaged as a precondition.
279      _Tp&
280      _M_get() noexcept
281      { return _M_payload; }
282
283      constexpr const _Tp&
284      _M_get() const noexcept
285      { return _M_payload; }
286
287      // The _M_construct operation has !_M_engaged as a precondition
288      // while _M_destruct has _M_engaged as a precondition.
289      template<typename... _Args>
290        void
291        _M_construct(_Args&&... __args)
292        noexcept(is_nothrow_constructible<_Stored_type, _Args...>())
293        {
294          ::new (std::__addressof(this->_M_payload))
295            _Stored_type(std::forward<_Args>(__args)...);
296          this->_M_engaged = true;
297        }
298
299      void
300      _M_destruct()
301      {
302        this->_M_engaged = false;
303        this->_M_payload.~_Stored_type();
304      }
305
306      // _M_reset is a 'safe' operation with no precondition.
307      void
308      _M_reset()
309      {
310        if (this->_M_engaged)
311          this->_M_destruct();
312      }
313
314    private:
315      struct _Empty_byte { };
316      union {
317          _Empty_byte _M_empty;
318          _Stored_type _M_payload;
319      };
320      bool _M_engaged = false;
321    };
322
323  /// Partial specialization that is exactly identical to the primary template
324  /// save for not providing a destructor, to fulfill triviality requirements.
325  template<typename _Tp>
326    class _Optional_base<_Tp, false>
327    {
328    private:
329      using _Stored_type = typename remove_const<_Tp>::type;
330
331    public:
332      constexpr _Optional_base() noexcept
333      : _M_empty{} { }
334
335      constexpr _Optional_base(nullopt_t) noexcept
336      : _Optional_base{} { }
337
338      constexpr _Optional_base(const _Tp& __t)
339      : _M_payload(__t), _M_engaged(true) { }
340
341      constexpr _Optional_base(_Tp&& __t)
342      : _M_payload(std::move(__t)), _M_engaged(true) { }
343
344      template<typename... _Args>
345        constexpr explicit _Optional_base(in_place_t, _Args&&... __args)
346        : _M_payload(std::forward<_Args>(__args)...), _M_engaged(true) { }
347
348      template<typename _Up, typename... _Args,
349               typename enable_if<is_constructible<_Tp,
350                                                   initializer_list<_Up>&,
351                                                   _Args&&...>::value,
352                                  int>::type...>
353        constexpr explicit _Optional_base(in_place_t,
354                                          initializer_list<_Up> __il,
355                                          _Args&&... __args)
356        : _M_payload(__il, std::forward<_Args>(__args)...),
357          _M_engaged(true) { }
358
359      _Optional_base(const _Optional_base& __other)
360      {
361        if (__other._M_engaged)
362          this->_M_construct(__other._M_get());
363      }
364
365      _Optional_base(_Optional_base&& __other)
366      noexcept(is_nothrow_move_constructible<_Tp>())
367      {
368        if (__other._M_engaged)
369          this->_M_construct(std::move(__other._M_get()));
370      }
371
372      _Optional_base&
373      operator=(const _Optional_base& __other)
374      {
375	if (this->_M_engaged && __other._M_engaged)
376	  this->_M_get() = __other._M_get();
377	else
378	  {
379	    if (__other._M_engaged)
380	      this->_M_construct(__other._M_get());
381	    else
382	      this->_M_reset();
383	  }
384	return *this;
385      }
386
387      _Optional_base&
388      operator=(_Optional_base&& __other)
389      noexcept(__and_<is_nothrow_move_constructible<_Tp>,
390		      is_nothrow_move_assignable<_Tp>>())
391      {
392	if (this->_M_engaged && __other._M_engaged)
393	  this->_M_get() = std::move(__other._M_get());
394	else
395	  {
396	    if (__other._M_engaged)
397	      this->_M_construct(std::move(__other._M_get()));
398	    else
399	      this->_M_reset();
400	  }
401	return *this;
402      }
403
404      // Sole difference
405      // ~_Optional_base() noexcept = default;
406
407    protected:
408      constexpr bool _M_is_engaged() const noexcept
409      { return this->_M_engaged; }
410
411      _Tp&
412      _M_get() noexcept
413      { return _M_payload; }
414
415      constexpr const _Tp&
416      _M_get() const noexcept
417      { return _M_payload; }
418
419      template<typename... _Args>
420        void
421        _M_construct(_Args&&... __args)
422        noexcept(is_nothrow_constructible<_Stored_type, _Args...>())
423        {
424          ::new (std::__addressof(this->_M_payload))
425            _Stored_type(std::forward<_Args>(__args)...);
426          this->_M_engaged = true;
427        }
428
429      void
430      _M_destruct()
431      {
432        this->_M_engaged = false;
433        this->_M_payload.~_Stored_type();
434      }
435
436      void
437      _M_reset()
438      {
439        if (this->_M_engaged)
440          this->_M_destruct();
441      }
442
443    private:
444      struct _Empty_byte { };
445      union
446      {
447	_Empty_byte _M_empty;
448	_Stored_type _M_payload;
449      };
450      bool _M_engaged = false;
451    };
452
453  /**
454    * @brief Class template for optional values.
455    */
456  template<typename _Tp>
457    class optional
458    : private _Optional_base<_Tp>,
459      private _Enable_copy_move<
460        // Copy constructor.
461        is_copy_constructible<_Tp>::value,
462        // Copy assignment.
463        __and_<is_copy_constructible<_Tp>, is_copy_assignable<_Tp>>::value,
464        // Move constructor.
465        is_move_constructible<_Tp>::value,
466        // Move assignment.
467        __and_<is_move_constructible<_Tp>, is_move_assignable<_Tp>>::value,
468        // Unique tag type.
469        optional<_Tp>>
470    {
471      static_assert(__and_<__not_<is_same<typename remove_cv<_Tp>::type,
472					  nullopt_t>>,
473			   __not_<is_same<typename remove_cv<_Tp>::type,
474					  in_place_t>>,
475			   __not_<is_reference<_Tp>>>(),
476                    "Invalid instantiation of optional<T>");
477
478    private:
479      using _Base = _Optional_base<_Tp>;
480
481    public:
482      using value_type = _Tp;
483
484      // _Optional_base has the responsibility for construction.
485      using _Base::_Base;
486
487      // [X.Y.4.3] (partly) Assignment.
488      optional&
489      operator=(nullopt_t) noexcept
490      {
491        this->_M_reset();
492        return *this;
493      }
494
495      template<typename _Up>
496        typename enable_if<
497                 is_same<_Tp, typename decay<_Up>::type>::value,
498                 optional&
499               >::type
500        operator=(_Up&& __u)
501        {
502          static_assert(__and_<is_constructible<_Tp, _Up>,
503			       is_assignable<_Tp&, _Up>>(),
504                        "Cannot assign to value type from argument");
505
506          if (this->_M_is_engaged())
507            this->_M_get() = std::forward<_Up>(__u);
508          else
509            this->_M_construct(std::forward<_Up>(__u));
510
511          return *this;
512        }
513
514      template<typename... _Args>
515	void
516	emplace(_Args&&... __args)
517	{
518	  static_assert(is_constructible<_Tp, _Args&&...>(),
519			"Cannot emplace value type from arguments");
520
521	  this->_M_reset();
522	  this->_M_construct(std::forward<_Args>(__args)...);
523	}
524
525      template<typename _Up, typename... _Args>
526        typename enable_if<
527                 is_constructible<_Tp,
528                                  initializer_list<_Up>&,
529                                  _Args&&...>::value
530               >::type
531	emplace(initializer_list<_Up> __il, _Args&&... __args)
532	{
533	  this->_M_reset();
534	  this->_M_construct(__il, std::forward<_Args>(__args)...);
535	}
536
537      // [X.Y.4.2] Destructor is implicit, implemented in _Optional_base.
538
539      // [X.Y.4.4] Swap.
540      void
541      swap(optional& __other)
542      noexcept(is_nothrow_move_constructible<_Tp>()
543               && noexcept(swap(declval<_Tp&>(), declval<_Tp&>())))
544      {
545        using std::swap;
546
547        if (this->_M_is_engaged() && __other._M_is_engaged())
548          swap(this->_M_get(), __other._M_get());
549        else if (this->_M_is_engaged())
550	  {
551	    __other._M_construct(std::move(this->_M_get()));
552	    this->_M_destruct();
553	  }
554        else if (__other._M_is_engaged())
555	  {
556	    this->_M_construct(std::move(__other._M_get()));
557	    __other._M_destruct();
558	  }
559      }
560
561      // [X.Y.4.5] Observers.
562      constexpr const _Tp*
563      operator->() const
564      { return __constexpr_addressof(this->_M_get()); }
565
566      _Tp*
567      operator->()
568      { return std::__addressof(this->_M_get()); }
569
570      constexpr const _Tp&
571      operator*() const
572      { return this->_M_get(); }
573
574      _Tp&
575      operator*()
576      { return this->_M_get(); }
577
578      constexpr explicit operator bool() const noexcept
579      { return this->_M_is_engaged(); }
580
581      constexpr const _Tp&
582      value() const
583      {
584	return this->_M_is_engaged()
585	  ?  this->_M_get()
586	  : (__throw_bad_optional_access("Attempt to access value of a "
587		                         "disengaged optional object"),
588	     this->_M_get());
589      }
590
591      _Tp&
592      value()
593      {
594        if (this->_M_is_engaged())
595          return this->_M_get();
596
597        __throw_bad_optional_access("Attempt to access value of a "
598				    "disengaged optional object");
599      }
600
601      template<typename _Up>
602	constexpr _Tp
603	value_or(_Up&& __u) const&
604	{
605	  static_assert(__and_<is_copy_constructible<_Tp>,
606			       is_convertible<_Up&&, _Tp>>(),
607			"Cannot return value");
608
609	  return this->_M_is_engaged()
610	    ? this->_M_get()
611	    : static_cast<_Tp>(std::forward<_Up>(__u));
612	}
613
614      template<typename _Up>
615	_Tp
616	value_or(_Up&& __u) &&
617	{
618	  static_assert(__and_<is_move_constructible<_Tp>,
619			       is_convertible<_Up&&, _Tp>>(),
620			"Cannot return value" );
621
622	  return this->_M_is_engaged()
623	    ? std::move(this->_M_get())
624	    : static_cast<_Tp>(std::forward<_Up>(__u));
625	}
626    };
627
628  // [X.Y.8] Comparisons between optional values.
629  template<typename _Tp>
630    constexpr bool
631    operator==(const optional<_Tp>& __lhs, const optional<_Tp>& __rhs)
632    {
633      return static_cast<bool>(__lhs) == static_cast<bool>(__rhs)
634	     && (!__lhs || *__lhs == *__rhs);
635    }
636
637  template<typename _Tp>
638    constexpr bool
639    operator!=(const optional<_Tp>& __lhs, const optional<_Tp>& __rhs)
640    { return !(__lhs == __rhs); }
641
642  template<typename _Tp>
643    constexpr bool
644    operator<(const optional<_Tp>& __lhs, const optional<_Tp>& __rhs)
645    {
646      return static_cast<bool>(__rhs) && (!__lhs || *__lhs < *__rhs);
647    }
648
649  template<typename _Tp>
650    constexpr bool
651    operator>(const optional<_Tp>& __lhs, const optional<_Tp>& __rhs)
652    { return __rhs < __lhs; }
653
654  template<typename _Tp>
655    constexpr bool
656    operator<=(const optional<_Tp>& __lhs, const optional<_Tp>& __rhs)
657    { return !(__rhs < __lhs); }
658
659  template<typename _Tp>
660    constexpr bool
661    operator>=(const optional<_Tp>& __lhs, const optional<_Tp>& __rhs)
662    { return !(__lhs < __rhs); }
663
664  // [X.Y.9] Comparisons with nullopt.
665  template<typename _Tp>
666    constexpr bool
667    operator==(const optional<_Tp>& __lhs, nullopt_t) noexcept
668    { return !__lhs; }
669
670  template<typename _Tp>
671    constexpr bool
672    operator==(nullopt_t, const optional<_Tp>& __rhs) noexcept
673    { return !__rhs; }
674
675  template<typename _Tp>
676    constexpr bool
677    operator!=(const optional<_Tp>& __lhs, nullopt_t) noexcept
678    { return static_cast<bool>(__lhs); }
679
680  template<typename _Tp>
681    constexpr bool
682    operator!=(nullopt_t, const optional<_Tp>& __rhs) noexcept
683    { return static_cast<bool>(__rhs); }
684
685  template<typename _Tp>
686    constexpr bool
687    operator<(const optional<_Tp>& /* __lhs */, nullopt_t) noexcept
688    { return false; }
689
690  template<typename _Tp>
691    constexpr bool
692    operator<(nullopt_t, const optional<_Tp>& __rhs) noexcept
693    { return static_cast<bool>(__rhs); }
694
695  template<typename _Tp>
696    constexpr bool
697    operator>(const optional<_Tp>& __lhs, nullopt_t) noexcept
698    { return static_cast<bool>(__lhs); }
699
700  template<typename _Tp>
701    constexpr bool
702    operator>(nullopt_t, const optional<_Tp>& /* __rhs */) noexcept
703    { return false; }
704
705  template<typename _Tp>
706    constexpr bool
707    operator<=(const optional<_Tp>& __lhs, nullopt_t) noexcept
708    { return !__lhs; }
709
710  template<typename _Tp>
711    constexpr bool
712    operator<=(nullopt_t, const optional<_Tp>& /* __rhs */) noexcept
713    { return true; }
714
715  template<typename _Tp>
716    constexpr bool
717    operator>=(const optional<_Tp>& /* __lhs */, nullopt_t) noexcept
718    { return true; }
719
720  template<typename _Tp>
721    constexpr bool
722    operator>=(nullopt_t, const optional<_Tp>& __rhs) noexcept
723    { return !__rhs; }
724
725  // [X.Y.10] Comparisons with value type.
726  template<typename _Tp>
727    constexpr bool
728    operator==(const optional<_Tp>& __lhs, const _Tp& __rhs)
729    { return __lhs && *__lhs == __rhs; }
730
731  template<typename _Tp>
732    constexpr bool
733    operator==(const _Tp& __lhs, const optional<_Tp>& __rhs)
734    { return __rhs && __lhs == *__rhs; }
735
736  template<typename _Tp>
737    constexpr bool
738    operator!=(const optional<_Tp>& __lhs, _Tp const& __rhs)
739    { return !__lhs || !(*__lhs == __rhs); }
740
741  template<typename _Tp>
742    constexpr bool
743    operator!=(const _Tp& __lhs, const optional<_Tp>& __rhs)
744    { return !__rhs || !(__lhs == *__rhs); }
745
746  template<typename _Tp>
747    constexpr bool
748    operator<(const optional<_Tp>& __lhs, const _Tp& __rhs)
749    { return !__lhs || *__lhs < __rhs; }
750
751  template<typename _Tp>
752    constexpr bool
753    operator<(const _Tp& __lhs, const optional<_Tp>& __rhs)
754    { return __rhs && __lhs < *__rhs; }
755
756  template<typename _Tp>
757    constexpr bool
758    operator>(const optional<_Tp>& __lhs, const _Tp& __rhs)
759    { return __lhs && __rhs < *__lhs; }
760
761  template<typename _Tp>
762    constexpr bool
763    operator>(const _Tp& __lhs, const optional<_Tp>& __rhs)
764    { return !__rhs || *__rhs < __lhs; }
765
766  template<typename _Tp>
767    constexpr bool
768    operator<=(const optional<_Tp>& __lhs, const _Tp& __rhs)
769    { return !__lhs || !(__rhs < *__lhs); }
770
771  template<typename _Tp>
772    constexpr bool
773    operator<=(const _Tp& __lhs, const optional<_Tp>& __rhs)
774    { return __rhs && !(*__rhs < __lhs); }
775
776  template<typename _Tp>
777    constexpr bool
778    operator>=(const optional<_Tp>& __lhs, const _Tp& __rhs)
779    { return __lhs && !(*__lhs < __rhs); }
780
781  template<typename _Tp>
782    constexpr bool
783    operator>=(const _Tp& __lhs, const optional<_Tp>& __rhs)
784    { return !__rhs || !(__lhs < *__rhs); }
785
786  // [X.Y.11]
787  template<typename _Tp>
788    inline void
789    swap(optional<_Tp>& __lhs, optional<_Tp>& __rhs)
790    noexcept(noexcept(__lhs.swap(__rhs)))
791    { __lhs.swap(__rhs); }
792
793  template<typename _Tp>
794    constexpr optional<typename decay<_Tp>::type>
795    make_optional(_Tp&& __t)
796    { return optional<typename decay<_Tp>::type> { std::forward<_Tp>(__t) }; }
797
798  // @} group optional
799_GLIBCXX_END_NAMESPACE_VERSION
800}
801
802  // [X.Y.12]
803  template<typename _Tp>
804    struct hash<experimental::optional<_Tp>>
805    {
806      using result_type = size_t;
807      using argument_type = experimental::optional<_Tp>;
808
809      size_t
810      operator()(const experimental::optional<_Tp>& __t) const
811      noexcept(noexcept(hash<_Tp> {}(*__t)))
812      {
813        // We pick an arbitrary hash for disengaged optionals which hopefully
814        // usual values of _Tp won't typically hash to.
815        constexpr size_t __magic_disengaged_hash = static_cast<size_t>(-3333);
816        return __t ? hash<_Tp> {}(*__t) : __magic_disengaged_hash;
817      }
818    };
819}
820
821#endif // C++14
822
823#endif // _GLIBCXX_EXPERIMENTAL_OPTIONAL
824