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