libstdc++
optional
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 
51 namespace std _GLIBCXX_VISIBILITY(default)
52 {
53 namespace experimental
54 {
55 inline 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