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