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