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