1// <optional> -*- C++ -*-
2
3// Copyright (C) 2013-2017 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 include/optional
26 * This is a Standard C++ Library header.
27 */
28
29#ifndef _GLIBCXX_OPTIONAL
30#define _GLIBCXX_OPTIONAL 1
31
32#pragma GCC system_header
33
34#if __cplusplus >= 201703L
35
36#include <utility>
37#include <type_traits>
38#include <stdexcept>
39#include <new>
40#include <initializer_list>
41#include <bits/functexcept.h>
42#include <bits/functional_hash.h>
43#include <bits/enable_special_members.h>
44
45namespace std _GLIBCXX_VISIBILITY(default)
46{
47_GLIBCXX_BEGIN_NAMESPACE_VERSION
48
49 /**
50 * @addtogroup utilities
51 * @{
52 */
53
54#define __cpp_lib_optional 201603
55
56 template<typename _Tp>
57 class optional;
58
59 /// Tag type to disengage optional objects.
60 struct nullopt_t
61 {
62 // Do not user-declare default constructor at all for
63 // optional_value = {} syntax to work.
64 // nullopt_t() = delete;
65
66 // Used for constructing nullopt.
67 enum class _Construct { _Token };
68
69 // Must be constexpr for nullopt_t to be literal.
70 explicit constexpr nullopt_t(_Construct) { }
71 };
72
73 /// Tag to disengage optional objects.
74 inline constexpr nullopt_t nullopt { nullopt_t::_Construct::_Token };
75
76 /**
77 * @brief Exception class thrown when a disengaged optional object is
78 * dereferenced.
79 * @ingroup exceptions
80 */
81 class bad_optional_access : public exception
82 {
83 public:
84 bad_optional_access() { }
85 virtual const char* what() const noexcept override
86 {return "bad optional access";}
87
88 virtual ~bad_optional_access() noexcept = default;
89 };
90
91 void
92 __throw_bad_optional_access()
93 __attribute__((__noreturn__));
94
95 // XXX Does not belong here.
96 inline void
97 __throw_bad_optional_access()
98 { _GLIBCXX_THROW_OR_ABORT(bad_optional_access()); }
99
100
101 // Payload for constexpr optionals.
102 template <typename _Tp,
103 bool /*_TrivialCopyMove*/ =
104 is_trivially_copy_constructible<_Tp>::value
105 && is_trivially_move_constructible<_Tp>::value,
106 bool /*_ShouldProvideDestructor*/ =
107 is_trivially_destructible<_Tp>::value>
108 struct _Optional_payload
109 {
110 constexpr _Optional_payload()
111 : _M_empty() {}
112
113 template<typename... _Args>
114 constexpr _Optional_payload(in_place_t, _Args&&... __args)
115 : _M_payload(std::forward<_Args>(__args)...),
116 _M_engaged(true)
117 {}
118
119 template<typename _Up, typename... _Args>
120 constexpr _Optional_payload(std::initializer_list<_Up> __il,
121 _Args&&... __args)
122 : _M_payload(__il, std::forward<_Args>(__args)...),
123 _M_engaged(true) {}
124
125 template <class _Up> struct __ctor_tag {};
126
127 constexpr _Optional_payload(__ctor_tag<bool>,
128 const _Tp& __other)
129 : _M_payload(__other),
130 _M_engaged(true)
131 {}
132
133 constexpr _Optional_payload(__ctor_tag<void>)
134 : _M_empty()
135 {}
136
137 constexpr _Optional_payload(__ctor_tag<bool>, _Tp&& __other)
138 : _M_payload(std::move(__other)),
139 _M_engaged(true)
140 {}
141
142 constexpr _Optional_payload(bool __engaged,
143 const _Optional_payload& __other)
144 : _Optional_payload(__engaged ?
145 _Optional_payload(__ctor_tag<bool>{},
146 __other._M_payload) :
147 _Optional_payload(__ctor_tag<void>{}))
148 {}
149
150 constexpr _Optional_payload(bool __engaged,
151 _Optional_payload&& __other)
152 : _Optional_payload(__engaged
153 ? _Optional_payload(__ctor_tag<bool>{},
154 std::move(__other._M_payload))
155 : _Optional_payload(__ctor_tag<void>{}))
156 {}
157
158 using _Stored_type = remove_const_t<_Tp>;
159 struct _Empty_byte { };
160 union {
161 _Empty_byte _M_empty;
162 _Stored_type _M_payload;
163 };
164 bool _M_engaged = false;
165 };
166
167 // Payload for non-constexpr optionals with non-trivial destructor.
168 template <typename _Tp>
169 struct _Optional_payload<_Tp, false, false>
170 {
171 constexpr _Optional_payload()
172 : _M_empty() {}
173
174 template <typename... _Args>
175 constexpr _Optional_payload(in_place_t, _Args&&... __args)
176 : _M_payload(std::forward<_Args>(__args)...),
177 _M_engaged(true) {}
178
179 template<typename _Up, typename... _Args>
180 constexpr _Optional_payload(std::initializer_list<_Up> __il,
181 _Args&&... __args)
182 : _M_payload(__il, std::forward<_Args>(__args)...),
183 _M_engaged(true) {}
184 constexpr
185 _Optional_payload(bool __engaged, const _Optional_payload& __other)
186 : _Optional_payload(__other)
187 {}
188
189 constexpr
190 _Optional_payload(bool __engaged, _Optional_payload&& __other)
191 : _Optional_payload(std::move(__other))
192 {}
193
194 constexpr _Optional_payload(const _Optional_payload& __other)
195 {
196 if (__other._M_engaged)
197 this->_M_construct(__other._M_payload);
198 }
199
200 constexpr _Optional_payload(_Optional_payload&& __other)
201 {
202 if (__other._M_engaged)
203 this->_M_construct(std::move(__other._M_payload));
204 }
205
206 using _Stored_type = remove_const_t<_Tp>;
207 struct _Empty_byte { };
208 union {
209 _Empty_byte _M_empty;
210 _Stored_type _M_payload;
211 };
212 bool _M_engaged = false;
213
214 ~_Optional_payload()
215 {
216 if (_M_engaged)
217 _M_payload.~_Stored_type();
218 }
219
220 template<typename... _Args>
221 void
222 _M_construct(_Args&&... __args)
223 noexcept(is_nothrow_constructible<_Stored_type, _Args...>())
224 {
225 ::new ((void *) std::__addressof(this->_M_payload))
226 _Stored_type(std::forward<_Args>(__args)...);
227 this->_M_engaged = true;
228 }
229 };
230
231 // Payload for non-constexpr optionals with trivial destructor.
232 template <typename _Tp>
233 struct _Optional_payload<_Tp, false, true>
234 {
235 constexpr _Optional_payload()
236 : _M_empty() {}
237
238 template <typename... _Args>
239 constexpr _Optional_payload(in_place_t, _Args&&... __args)
240 : _M_payload(std::forward<_Args>(__args)...),
241 _M_engaged(true) {}
242
243 template<typename _Up, typename... _Args>
244 constexpr _Optional_payload(std::initializer_list<_Up> __il,
245 _Args&&... __args)
246 : _M_payload(__il, std::forward<_Args>(__args)...),
247 _M_engaged(true) {}
248 constexpr
249 _Optional_payload(bool __engaged, const _Optional_payload& __other)
250 : _Optional_payload(__other)
251 {}
252
253 constexpr
254 _Optional_payload(bool __engaged, _Optional_payload&& __other)
255 : _Optional_payload(std::move(__other))
256 {}
257
258 constexpr _Optional_payload(const _Optional_payload& __other)
259 {
260 if (__other._M_engaged)
261 this->_M_construct(__other._M_payload);
262 }
263
264 constexpr _Optional_payload(_Optional_payload&& __other)
265 {
266 if (__other._M_engaged)
267 this->_M_construct(std::move(__other._M_payload));
268 }
269
270 using _Stored_type = remove_const_t<_Tp>;
271 struct _Empty_byte { };
272 union {
273 _Empty_byte _M_empty;
274 _Stored_type _M_payload;
275 };
276 bool _M_engaged = false;
277
278 template<typename... _Args>
279 void
280 _M_construct(_Args&&... __args)
281 noexcept(is_nothrow_constructible<_Stored_type, _Args...>())
282 {
283 ::new ((void *) std::__addressof(this->_M_payload))
284 _Stored_type(std::forward<_Args>(__args)...);
285 this->_M_engaged = true;
286 }
287 };
288
289 /**
290 * @brief Class template that holds the necessary state for @ref optional
291 * and that has the responsibility for construction and the special members.
292 *
293 * Such a separate base class template is necessary in order to
294 * conditionally enable the special members (e.g. copy/move constructors).
295 * Note that this means that @ref _Optional_base implements the
296 * functionality for copy and move assignment, but not for converting
297 * assignment.
298 *
299 * @see optional, _Enable_special_members
300 */
301 template<typename _Tp>
302 class _Optional_base
303 {
304 private:
305 // Remove const to avoid prohibition of reusing object storage for
306 // const-qualified types in [3.8/9]. This is strictly internal
307 // and even optional itself is oblivious to it.
308 using _Stored_type = remove_const_t<_Tp>;
309
310 public:
311
312 // Constructors for disengaged optionals.
313 constexpr _Optional_base() noexcept
314 { }
315
316 constexpr _Optional_base(nullopt_t) noexcept
317 { }
318
319 // Constructors for engaged optionals.
320 template<typename... _Args,
321 enable_if_t<is_constructible_v<_Tp, _Args&&...>, bool> = false>
322 constexpr explicit _Optional_base(in_place_t, _Args&&... __args)
323 : _M_payload(in_place,
324 std::forward<_Args>(__args)...) { }
325
326 template<typename _Up, typename... _Args,
327 enable_if_t<is_constructible_v<_Tp,
328 initializer_list<_Up>&,
329 _Args&&...>, bool> = false>
330 constexpr explicit _Optional_base(in_place_t,
331 initializer_list<_Up> __il,
332 _Args&&... __args)
333 : _M_payload(in_place,
334 __il, std::forward<_Args>(__args)...)
335 { }
336
337 // Copy and move constructors.
338 constexpr _Optional_base(const _Optional_base& __other)
339 : _M_payload(__other._M_payload._M_engaged,
340 __other._M_payload)
341 { }
342
343 constexpr _Optional_base(_Optional_base&& __other)
344 noexcept(is_nothrow_move_constructible<_Tp>())
345 : _M_payload(__other._M_payload._M_engaged,
346 std::move(__other._M_payload))
347 { }
348
349 // Assignment operators.
350 _Optional_base&
351 operator=(const _Optional_base& __other)
352 {
353 if (this->_M_payload._M_engaged && __other._M_payload._M_engaged)
354 this->_M_get() = __other._M_get();
355 else
356 {
357 if (__other._M_payload._M_engaged)
358 this->_M_construct(__other._M_get());
359 else
360 this->_M_reset();
361 }
362
363 return *this;
364 }
365
366 _Optional_base&
367 operator=(_Optional_base&& __other)
368 noexcept(__and_<is_nothrow_move_constructible<_Tp>,
369 is_nothrow_move_assignable<_Tp>>())
370 {
371 if (this->_M_payload._M_engaged && __other._M_payload._M_engaged)
372 this->_M_get() = std::move(__other._M_get());
373 else
374 {
375 if (__other._M_payload._M_engaged)
376 this->_M_construct(std::move(__other._M_get()));
377 else
378 this->_M_reset();
379 }
380 return *this;
381 }
382 // The following functionality is also needed by optional, hence the
383 // protected accessibility.
384 protected:
385 constexpr bool _M_is_engaged() const noexcept
386 { return this->_M_payload._M_engaged; }
387
388 // The _M_get operations have _M_engaged as a precondition.
389 constexpr _Tp&
390 _M_get() noexcept
391 {
392 __glibcxx_assert(_M_is_engaged());
393 return this->_M_payload._M_payload;
394 }
395
396 constexpr const _Tp&
397 _M_get() const noexcept
398 {
399 __glibcxx_assert(_M_is_engaged());
400 return this->_M_payload._M_payload;
401 }
402
403 // The _M_construct operation has !_M_engaged as a precondition
404 // while _M_destruct has _M_engaged as a precondition.
405 template<typename... _Args>
406 void
407 _M_construct(_Args&&... __args)
408 noexcept(is_nothrow_constructible<_Stored_type, _Args...>())
409 {
410 ::new (std::__addressof(this->_M_payload._M_payload))
411 _Stored_type(std::forward<_Args>(__args)...);
412 this->_M_payload._M_engaged = true;
413 }
414
415 void
416 _M_destruct()
417 {
418 this->_M_payload._M_engaged = false;
419 this->_M_payload._M_payload.~_Stored_type();
420 }
421
422 // _M_reset is a 'safe' operation with no precondition.
423 void
424 _M_reset()
425 {
426 if (this->_M_payload._M_engaged)
427 this->_M_destruct();
428 }
429
430 private:
431 _Optional_payload<_Tp> _M_payload;
432 };
433
434 template<typename _Tp>
435 class optional;
436
437 template<typename _Tp, typename _Up>
438 using __converts_from_optional =
439 __or_<is_constructible<_Tp, const optional<_Up>&>,
440 is_constructible<_Tp, optional<_Up>&>,
441 is_constructible<_Tp, const optional<_Up>&&>,
442 is_constructible<_Tp, optional<_Up>&&>,
443 is_convertible<const optional<_Up>&, _Tp>,
444 is_convertible<optional<_Up>&, _Tp>,
445 is_convertible<const optional<_Up>&&, _Tp>,
446 is_convertible<optional<_Up>&&, _Tp>>;
447
448 template<typename _Tp, typename _Up>
449 using __assigns_from_optional =
450 __or_<is_assignable<_Tp&, const optional<_Up>&>,
451 is_assignable<_Tp&, optional<_Up>&>,
452 is_assignable<_Tp&, const optional<_Up>&&>,
453 is_assignable<_Tp&, optional<_Up>&&>>;
454
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(!is_same_v<remove_cv_t<_Tp>, nullopt_t>);
474 static_assert(!is_same_v<remove_cv_t<_Tp>, in_place_t>);
475 static_assert(!is_reference_v<_Tp>);
476
477 private:
478 using _Base = _Optional_base<_Tp>;
479
480 public:
481 using value_type = _Tp;
482
483 constexpr optional() = default;
484
485 constexpr optional(nullopt_t) noexcept
486 : _Base(nullopt) { }
487
488 // Converting constructors for engaged optionals.
489 template <typename _Up = _Tp,
490 enable_if_t<__and_<
491 __not_<is_same<optional<_Tp>, decay_t<_Up>>>,
492 __not_<is_same<in_place_t, decay_t<_Up>>>,
493 is_constructible<_Tp, _Up&&>,
494 is_convertible<_Up&&, _Tp>
495 >::value, bool> = true>
496 constexpr optional(_Up&& __t)
497 : _Base(std::in_place, std::forward<_Up>(__t)) { }
498
499 template <typename _Up = _Tp,
500 enable_if_t<__and_<
501 __not_<is_same<optional<_Tp>, decay_t<_Up>>>,
502 __not_<is_same<in_place_t, decay_t<_Up>>>,
503 is_constructible<_Tp, _Up&&>,
504 __not_<is_convertible<_Up&&, _Tp>>
505 >::value, bool> = false>
506 explicit constexpr optional(_Up&& __t)
507 : _Base(std::in_place, std::forward<_Up>(__t)) { }
508
509 template <typename _Up,
510 enable_if_t<__and_<
511 __not_<is_same<_Tp, _Up>>,
512 is_constructible<_Tp, const _Up&>,
513 is_convertible<const _Up&, _Tp>,
514 __not_<__converts_from_optional<_Tp, _Up>>
515 >::value, bool> = true>
516 constexpr optional(const optional<_Up>& __t)
517 {
518 if (__t)
519 emplace(*__t);
520 }
521
522 template <typename _Up,
523 enable_if_t<__and_<
524 __not_<is_same<_Tp, _Up>>,
525 is_constructible<_Tp, const _Up&>,
526 __not_<is_convertible<const _Up&, _Tp>>,
527 __not_<__converts_from_optional<_Tp, _Up>>
528 >::value, bool> = false>
529 explicit constexpr optional(const optional<_Up>& __t)
530 {
531 if (__t)
532 emplace(*__t);
533 }
534
535 template <typename _Up,
536 enable_if_t<__and_<
537 __not_<is_same<_Tp, _Up>>,
538 is_constructible<_Tp, _Up&&>,
539 is_convertible<_Up&&, _Tp>,
540 __not_<__converts_from_optional<_Tp, _Up>>
541 >::value, bool> = true>
542 constexpr optional(optional<_Up>&& __t)
543 {
544 if (__t)
545 emplace(std::move(*__t));
546 }
547
548 template <typename _Up,
549 enable_if_t<__and_<
550 __not_<is_same<_Tp, _Up>>,
551 is_constructible<_Tp, _Up&&>,
552 __not_<is_convertible<_Up&&, _Tp>>,
553 __not_<__converts_from_optional<_Tp, _Up>>
554 >::value, bool> = false>
555 explicit constexpr optional(optional<_Up>&& __t)
556 {
557 if (__t)
558 emplace(std::move(*__t));
559 }
560
561 template<typename... _Args,
562 enable_if_t<is_constructible_v<_Tp, _Args&&...>, bool> = false>
563 explicit constexpr optional(in_place_t, _Args&&... __args)
564 : _Base(std::in_place, std::forward<_Args>(__args)...) { }
565
566 template<typename _Up, typename... _Args,
567 enable_if_t<is_constructible_v<_Tp,
568 initializer_list<_Up>&,
569 _Args&&...>, bool> = false>
570 explicit constexpr optional(in_place_t,
571 initializer_list<_Up> __il,
572 _Args&&... __args)
573 : _Base(std::in_place, __il, std::forward<_Args>(__args)...) { }
574
575 // Assignment operators.
576 optional&
577 operator=(nullopt_t) noexcept
578 {
579 this->_M_reset();
580 return *this;
581 }
582
583 template<typename _Up = _Tp>
584 enable_if_t<__and_<
585 __not_<is_same<optional<_Tp>, decay_t<_Up>>>,
586 is_constructible<_Tp, _Up>,
587 __not_<__and_<is_scalar<_Tp>,
588 is_same<_Tp, decay_t<_Up>>>>,
589 is_assignable<_Tp&, _Up>>::value,
590 optional&>
591 operator=(_Up&& __u)
592 {
593 if (this->_M_is_engaged())
594 this->_M_get() = std::forward<_Up>(__u);
595 else
596 this->_M_construct(std::forward<_Up>(__u));
597
598 return *this;
599 }
600
601 template<typename _Up>
602 enable_if_t<__and_<
603 __not_<is_same<_Tp, _Up>>,
604 is_constructible<_Tp, const _Up&>,
605 is_assignable<_Tp&, _Up>,
606 __not_<__converts_from_optional<_Tp, _Up>>,
607 __not_<__assigns_from_optional<_Tp, _Up>>
608 >::value,
609 optional&>
610 operator=(const optional<_Up>& __u)
611 {
612 if (__u)
613 {
614 if (this->_M_is_engaged())
615 this->_M_get() = *__u;
616 else
617 this->_M_construct(*__u);
618 }
619 else
620 {
621 this->_M_reset();
622 }
623 return *this;
624 }
625
626 template<typename _Up>
627 enable_if_t<__and_<
628 __not_<is_same<_Tp, _Up>>,
629 is_constructible<_Tp, _Up>,
630 is_assignable<_Tp&, _Up>,
631 __not_<__converts_from_optional<_Tp, _Up>>,
632 __not_<__assigns_from_optional<_Tp, _Up>>
633 >::value,
634 optional&>
635 operator=(optional<_Up>&& __u)
636 {
637 if (__u)
638 {
639 if (this->_M_is_engaged())
640 this->_M_get() = std::move(*__u);
641 else
642 this->_M_construct(std::move(*__u));
643 }
644 else
645 {
646 this->_M_reset();
647 }
648
649 return *this;
650 }
651
652 template<typename... _Args>
653 enable_if_t<is_constructible<_Tp, _Args&&...>::value, _Tp&>
654 emplace(_Args&&... __args)
655 {
656 this->_M_reset();
657 this->_M_construct(std::forward<_Args>(__args)...);
658 return this->_M_get();
659 }
660
661 template<typename _Up, typename... _Args>
662 enable_if_t<is_constructible<_Tp, initializer_list<_Up>&,
663 _Args&&...>::value, _Tp&>
664 emplace(initializer_list<_Up> __il, _Args&&... __args)
665 {
666 this->_M_reset();
667 this->_M_construct(__il, std::forward<_Args>(__args)...);
668 return this->_M_get();
669 }
670
671 // Destructor is implicit, implemented in _Optional_base.
672
673 // Swap.
674 void
675 swap(optional& __other)
676 noexcept(is_nothrow_move_constructible<_Tp>()
677 && is_nothrow_swappable_v<_Tp>)
678 {
679 using std::swap;
680
681 if (this->_M_is_engaged() && __other._M_is_engaged())
682 swap(this->_M_get(), __other._M_get());
683 else if (this->_M_is_engaged())
684 {
685 __other._M_construct(std::move(this->_M_get()));
686 this->_M_destruct();
687 }
688 else if (__other._M_is_engaged())
689 {
690 this->_M_construct(std::move(__other._M_get()));
691 __other._M_destruct();
692 }
693 }
694
695 // Observers.
696 constexpr const _Tp*
697 operator->() const
698 { return std::__addressof(this->_M_get()); }
699
700 _Tp*
701 operator->()
702 { return std::__addressof(this->_M_get()); }
703
704 constexpr const _Tp&
705 operator*() const&
706 { return this->_M_get(); }
707
708 constexpr _Tp&
709 operator*()&
710 { return this->_M_get(); }
711
712 constexpr _Tp&&
713 operator*()&&
714 { return std::move(this->_M_get()); }
715
716 constexpr const _Tp&&
717 operator*() const&&
718 { return std::move(this->_M_get()); }
719
720 constexpr explicit operator bool() const noexcept
721 { return this->_M_is_engaged(); }
722
723 constexpr bool has_value() const noexcept
724 { return this->_M_is_engaged(); }
725
726 constexpr const _Tp&
727 value() const&
728 {
729 return this->_M_is_engaged()
730 ? this->_M_get()
731 : (__throw_bad_optional_access(),
732 this->_M_get());
733 }
734
735 constexpr _Tp&
736 value()&
737 {
738 return this->_M_is_engaged()
739 ? this->_M_get()
740 : (__throw_bad_optional_access(),
741 this->_M_get());
742 }
743
744 constexpr _Tp&&
745 value()&&
746 {
747 return this->_M_is_engaged()
748 ? std::move(this->_M_get())
749 : (__throw_bad_optional_access(),
750 std::move(this->_M_get()));
751 }
752
753 constexpr const _Tp&&
754 value() const&&
755 {
756 return this->_M_is_engaged()
757 ? std::move(this->_M_get())
758 : (__throw_bad_optional_access(),
759 std::move(this->_M_get()));
760 }
761
762 template<typename _Up>
763 constexpr _Tp
764 value_or(_Up&& __u) const&
765 {
766 static_assert(is_copy_constructible_v<_Tp>);
767 static_assert(is_convertible_v<_Up&&, _Tp>);
768
769 return this->_M_is_engaged()
770 ? this->_M_get()
771 : static_cast<_Tp>(std::forward<_Up>(__u));
772 }
773
774 template<typename _Up>
775 _Tp
776 value_or(_Up&& __u) &&
777 {
778 static_assert(is_move_constructible_v<_Tp>);
779 static_assert(is_convertible_v<_Up&&, _Tp>);
780
781 return this->_M_is_engaged()
782 ? std::move(this->_M_get())
783 : static_cast<_Tp>(std::forward<_Up>(__u));
784 }
785 void reset() noexcept { this->_M_reset(); }
786 };
787
788 template<typename _Tp>
789 using __optional_relop_t =
790 enable_if_t<is_convertible<_Tp, bool>::value, bool>;
791
792 // Comparisons between optional values.
793 template<typename _Tp, typename _Up>
794 constexpr auto
795 operator==(const optional<_Tp>& __lhs, const optional<_Up>& __rhs)
796 -> __optional_relop_t<decltype(declval<_Tp>() == declval<_Up>())>
797 {
798 return static_cast<bool>(__lhs) == static_cast<bool>(__rhs)
799 && (!__lhs || *__lhs == *__rhs);
800 }
801
802 template<typename _Tp, typename _Up>
803 constexpr auto
804 operator!=(const optional<_Tp>& __lhs, const optional<_Up>& __rhs)
805 -> __optional_relop_t<decltype(declval<_Tp>() != declval<_Up>())>
806 {
807 return static_cast<bool>(__lhs) != static_cast<bool>(__rhs)
808 || (static_cast<bool>(__lhs) && *__lhs != *__rhs);
809 }
810
811 template<typename _Tp, typename _Up>
812 constexpr auto
813 operator<(const optional<_Tp>& __lhs, const optional<_Up>& __rhs)
814 -> __optional_relop_t<decltype(declval<_Tp>() < declval<_Up>())>
815 {
816 return static_cast<bool>(__rhs) && (!__lhs || *__lhs < *__rhs);
817 }
818
819 template<typename _Tp, typename _Up>
820 constexpr auto
821 operator>(const optional<_Tp>& __lhs, const optional<_Up>& __rhs)
822 -> __optional_relop_t<decltype(declval<_Tp>() > declval<_Up>())>
823 {
824 return static_cast<bool>(__lhs) && (!__rhs || *__lhs > *__rhs);
825 }
826
827 template<typename _Tp, typename _Up>
828 constexpr auto
829 operator<=(const optional<_Tp>& __lhs, const optional<_Up>& __rhs)
830 -> __optional_relop_t<decltype(declval<_Tp>() <= declval<_Up>())>
831 {
832 return !__lhs || (static_cast<bool>(__rhs) && *__lhs <= *__rhs);
833 }
834
835 template<typename _Tp, typename _Up>
836 constexpr auto
837 operator>=(const optional<_Tp>& __lhs, const optional<_Up>& __rhs)
838 -> __optional_relop_t<decltype(declval<_Tp>() >= declval<_Up>())>
839 {
840 return !__rhs || (static_cast<bool>(__lhs) && *__lhs >= *__rhs);
841 }
842
843 // Comparisons with nullopt.
844 template<typename _Tp>
845 constexpr bool
846 operator==(const optional<_Tp>& __lhs, nullopt_t) noexcept
847 { return !__lhs; }
848
849 template<typename _Tp>
850 constexpr bool
851 operator==(nullopt_t, const optional<_Tp>& __rhs) noexcept
852 { return !__rhs; }
853
854 template<typename _Tp>
855 constexpr bool
856 operator!=(const optional<_Tp>& __lhs, nullopt_t) noexcept
857 { return static_cast<bool>(__lhs); }
858
859 template<typename _Tp>
860 constexpr bool
861 operator!=(nullopt_t, const optional<_Tp>& __rhs) noexcept
862 { return static_cast<bool>(__rhs); }
863
864 template<typename _Tp>
865 constexpr bool
866 operator<(const optional<_Tp>& /* __lhs */, nullopt_t) noexcept
867 { return false; }
868
869 template<typename _Tp>
870 constexpr bool
871 operator<(nullopt_t, const optional<_Tp>& __rhs) noexcept
872 { return static_cast<bool>(__rhs); }
873
874 template<typename _Tp>
875 constexpr bool
876 operator>(const optional<_Tp>& __lhs, nullopt_t) noexcept
877 { return static_cast<bool>(__lhs); }
878
879 template<typename _Tp>
880 constexpr bool
881 operator>(nullopt_t, const optional<_Tp>& /* __rhs */) noexcept
882 { return false; }
883
884 template<typename _Tp>
885 constexpr bool
886 operator<=(const optional<_Tp>& __lhs, nullopt_t) noexcept
887 { return !__lhs; }
888
889 template<typename _Tp>
890 constexpr bool
891 operator<=(nullopt_t, const optional<_Tp>& /* __rhs */) noexcept
892 { return true; }
893
894 template<typename _Tp>
895 constexpr bool
896 operator>=(const optional<_Tp>& /* __lhs */, nullopt_t) noexcept
897 { return true; }
898
899 template<typename _Tp>
900 constexpr bool
901 operator>=(nullopt_t, const optional<_Tp>& __rhs) noexcept
902 { return !__rhs; }
903
904 // Comparisons with value type.
905 template<typename _Tp, typename _Up>
906 constexpr auto
907 operator==(const optional<_Tp>& __lhs, const _Up& __rhs)
908 -> __optional_relop_t<decltype(declval<_Tp>() == declval<_Up>())>
909 { return __lhs && *__lhs == __rhs; }
910
911 template<typename _Tp, typename _Up>
912 constexpr auto
913 operator==(const _Up& __lhs, const optional<_Tp>& __rhs)
914 -> __optional_relop_t<decltype(declval<_Up>() == declval<_Tp>())>
915 { return __rhs && __lhs == *__rhs; }
916
917 template<typename _Tp, typename _Up>
918 constexpr auto
919 operator!=(const optional<_Tp>& __lhs, const _Up& __rhs)
920 -> __optional_relop_t<decltype(declval<_Tp>() != declval<_Up>())>
921 { return !__lhs || *__lhs != __rhs; }
922
923 template<typename _Tp, typename _Up>
924 constexpr auto
925 operator!=(const _Up& __lhs, const optional<_Tp>& __rhs)
926 -> __optional_relop_t<decltype(declval<_Up>() != declval<_Tp>())>
927 { return !__rhs || __lhs != *__rhs; }
928
929 template<typename _Tp, typename _Up>
930 constexpr auto
931 operator<(const optional<_Tp>& __lhs, const _Up& __rhs)
932 -> __optional_relop_t<decltype(declval<_Tp>() < declval<_Up>())>
933 { return !__lhs || *__lhs < __rhs; }
934
935 template<typename _Tp, typename _Up>
936 constexpr auto
937 operator<(const _Up& __lhs, const optional<_Tp>& __rhs)
938 -> __optional_relop_t<decltype(declval<_Up>() < declval<_Tp>())>
939 { return __rhs && __lhs < *__rhs; }
940
941 template<typename _Tp, typename _Up>
942 constexpr auto
943 operator>(const optional<_Tp>& __lhs, const _Up& __rhs)
944 -> __optional_relop_t<decltype(declval<_Tp>() > declval<_Up>())>
945 { return __lhs && *__lhs > __rhs; }
946
947 template<typename _Tp, typename _Up>
948 constexpr auto
949 operator>(const _Up& __lhs, const optional<_Tp>& __rhs)
950 -> __optional_relop_t<decltype(declval<_Up>() > declval<_Tp>())>
951 { return !__rhs || __lhs > *__rhs; }
952
953 template<typename _Tp, typename _Up>
954 constexpr auto
955 operator<=(const optional<_Tp>& __lhs, const _Up& __rhs)
956 -> __optional_relop_t<decltype(declval<_Tp>() <= declval<_Up>())>
957 { return !__lhs || *__lhs <= __rhs; }
958
959 template<typename _Tp, typename _Up>
960 constexpr auto
961 operator<=(const _Up& __lhs, const optional<_Tp>& __rhs)
962 -> __optional_relop_t<decltype(declval<_Up>() <= declval<_Tp>())>
963 { return __rhs && __lhs <= *__rhs; }
964
965 template<typename _Tp, typename _Up>
966 constexpr auto
967 operator>=(const optional<_Tp>& __lhs, const _Up& __rhs)
968 -> __optional_relop_t<decltype(declval<_Tp>() >= declval<_Up>())>
969 { return __lhs && *__lhs >= __rhs; }
970
971 template<typename _Tp, typename _Up>
972 constexpr auto
973 operator>=(const _Up& __lhs, const optional<_Tp>& __rhs)
974 -> __optional_relop_t<decltype(declval<_Up>() >= declval<_Tp>())>
975 { return !__rhs || __lhs >= *__rhs; }
976
977 // Swap and creation functions.
978
979 // _GLIBCXX_RESOLVE_LIB_DEFECTS
980 // 2748. swappable traits for optionals
981 template<typename _Tp>
982 inline enable_if_t<is_move_constructible_v<_Tp> && is_swappable_v<_Tp>>
983 swap(optional<_Tp>& __lhs, optional<_Tp>& __rhs)
984 noexcept(noexcept(__lhs.swap(__rhs)))
985 { __lhs.swap(__rhs); }
986
987 template<typename _Tp>
988 enable_if_t<!(is_move_constructible_v<_Tp> && is_swappable_v<_Tp>)>
989 swap(optional<_Tp>&, optional<_Tp>&) = delete;
990
991 template<typename _Tp>
992 constexpr optional<decay_t<_Tp>>
993 make_optional(_Tp&& __t)
994 { return optional<decay_t<_Tp>> { std::forward<_Tp>(__t) }; }
995
996 template<typename _Tp, typename ..._Args>
997 constexpr optional<_Tp>
998 make_optional(_Args&&... __args)
999 { return optional<_Tp> { in_place, std::forward<_Args>(__args)... }; }
1000
1001 template<typename _Tp, typename _Up, typename ..._Args>
1002 constexpr optional<_Tp>
1003 make_optional(initializer_list<_Up> __il, _Args&&... __args)
1004 { return optional<_Tp> { in_place, __il, std::forward<_Args>(__args)... }; }
1005
1006 // Hash.
1007
1008 template<typename _Tp, typename _Up = remove_const_t<_Tp>,
1009 bool = __poison_hash<_Up>::__enable_hash_call>
1010 struct __optional_hash_call_base
1011 {
1012 size_t
1013 operator()(const optional<_Tp>& __t) const
1014 noexcept(noexcept(hash<_Up>{}(*__t)))
1015 {
1016 // We pick an arbitrary hash for disengaged optionals which hopefully
1017 // usual values of _Tp won't typically hash to.
1018 constexpr size_t __magic_disengaged_hash = static_cast<size_t>(-3333);
1019 return __t ? hash<_Up>{}(*__t) : __magic_disengaged_hash;
1020 }
1021 };
1022
1023 template<typename _Tp, typename _Up>
1024 struct __optional_hash_call_base<_Tp, _Up, false> {};
1025
1026 template<typename _Tp>
1027 struct hash<optional<_Tp>>
1028 : private __poison_hash<remove_const_t<_Tp>>,
1029 public __optional_hash_call_base<_Tp>
1030 {
1031 using result_type [[__deprecated__]] = size_t;
1032 using argument_type [[__deprecated__]] = optional<_Tp>;
1033 };
1034
1035 template<typename _Tp>
1036 struct __is_fast_hash<hash<optional<_Tp>>> : __is_fast_hash<hash<_Tp>>
1037 { };
1038
1039 /// @}
1040
1041 template <typename _Tp> optional(_Tp) -> optional<_Tp>;
1042
1043_GLIBCXX_END_NAMESPACE_VERSION
1044} // namespace std
1045
1046#endif // C++17
1047
1048#endif // _GLIBCXX_OPTIONAL
1049