libstdc++
optional
Go to the documentation of this file.
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 
57 namespace std _GLIBCXX_VISIBILITY(default)
58 {
59 namespace experimental
60 {
61 inline 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