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 { return this->_M_payload._M_payload; }
392
393 constexpr const _Tp&
394 _M_get() const noexcept
395 { return this->_M_payload._M_payload; }
396
397 // The _M_construct operation has !_M_engaged as a precondition
398 // while _M_destruct has _M_engaged as a precondition.
399 template<typename... _Args>
400 void
401 _M_construct(_Args&&... __args)
402 noexcept(is_nothrow_constructible<_Stored_type, _Args...>())
403 {
404 ::new (std::__addressof(this->_M_payload._M_payload))
405 _Stored_type(std::forward<_Args>(__args)...);
406 this->_M_payload._M_engaged = true;
407 }
408
409 void
410 _M_destruct()
411 {
412 this->_M_payload._M_engaged = false;
413 this->_M_payload._M_payload.~_Stored_type();
414 }
415
416 // _M_reset is a 'safe' operation with no precondition.
417 void
418 _M_reset()
419 {
420 if (this->_M_payload._M_engaged)
421 this->_M_destruct();
422 }
423
424 private:
425 _Optional_payload<_Tp> _M_payload;
426 };
427
428 template<typename _Tp>
429 class optional;
430
431 template<typename _Tp, typename _Up>
432 using __converts_from_optional =
433 __or_<is_constructible<_Tp, const optional<_Up>&>,
434 is_constructible<_Tp, optional<_Up>&>,
435 is_constructible<_Tp, const optional<_Up>&&>,
436 is_constructible<_Tp, optional<_Up>&&>,
437 is_convertible<const optional<_Up>&, _Tp>,
438 is_convertible<optional<_Up>&, _Tp>,
439 is_convertible<const optional<_Up>&&, _Tp>,
440 is_convertible<optional<_Up>&&, _Tp>>;
441
442 template<typename _Tp, typename _Up>
443 using __assigns_from_optional =
444 __or_<is_assignable<_Tp&, const optional<_Up>&>,
445 is_assignable<_Tp&, optional<_Up>&>,
446 is_assignable<_Tp&, const optional<_Up>&&>,
447 is_assignable<_Tp&, optional<_Up>&&>>;
448
449 /**
450 * @brief Class template for optional values.
451 */
452 template<typename _Tp>
453 class optional
454 : private _Optional_base<_Tp>,
455 private _Enable_copy_move<
456 // Copy constructor.
457 is_copy_constructible<_Tp>::value,
458 // Copy assignment.
459 __and_<is_copy_constructible<_Tp>, is_copy_assignable<_Tp>>::value,
460 // Move constructor.
461 is_move_constructible<_Tp>::value,
462 // Move assignment.
463 __and_<is_move_constructible<_Tp>, is_move_assignable<_Tp>>::value,
464 // Unique tag type.
465 optional<_Tp>>
466 {
467 static_assert(__and_<__not_<is_same<remove_cv_t<_Tp>, nullopt_t>>,
468 __not_<is_same<remove_cv_t<_Tp>, in_place_t>>,
469 __not_<is_reference<_Tp>>>(),
470 "Invalid instantiation of optional<T>");
471
472 private:
473 using _Base = _Optional_base<_Tp>;
474
475 public:
476 using value_type = _Tp;
477
478 constexpr optional() = default;
479
480 constexpr optional(nullopt_t) noexcept
481 : _Base(nullopt) { }
482
483 // Converting constructors for engaged optionals.
484 template <typename _Up = _Tp,
485 enable_if_t<__and_<
486 __not_<is_same<optional<_Tp>, decay_t<_Up>>>,
487 __not_<is_same<in_place_t, decay_t<_Up>>>,
488 is_constructible<_Tp, _Up&&>,
489 is_convertible<_Up&&, _Tp>
490 >::value, bool> = true>
491 constexpr optional(_Up&& __t)
492 : _Base(std::in_place, std::forward<_Up>(__t)) { }
493
494 template <typename _Up = _Tp,
495 enable_if_t<__and_<
496 __not_<is_same<optional<_Tp>, decay_t<_Up>>>,
497 __not_<is_same<in_place_t, decay_t<_Up>>>,
498 is_constructible<_Tp, _Up&&>,
499 __not_<is_convertible<_Up&&, _Tp>>
500 >::value, bool> = false>
501 explicit constexpr optional(_Up&& __t)
502 : _Base(std::in_place, std::forward<_Up>(__t)) { }
503
504 template <typename _Up,
505 enable_if_t<__and_<
506 __not_<is_same<_Tp, _Up>>,
507 is_constructible<_Tp, const _Up&>,
508 is_convertible<const _Up&, _Tp>,
509 __not_<__converts_from_optional<_Tp, _Up>>
510 >::value, bool> = true>
511 constexpr optional(const optional<_Up>& __t)
512 {
513 if (__t)
514 emplace(*__t);
515 }
516
517 template <typename _Up,
518 enable_if_t<__and_<
519 __not_<is_same<_Tp, _Up>>,
520 is_constructible<_Tp, const _Up&>,
521 __not_<is_convertible<const _Up&, _Tp>>,
522 __not_<__converts_from_optional<_Tp, _Up>>
523 >::value, bool> = false>
524 explicit constexpr optional(const optional<_Up>& __t)
525 {
526 if (__t)
527 emplace(*__t);
528 }
529
530 template <typename _Up,
531 enable_if_t<__and_<
532 __not_<is_same<_Tp, _Up>>,
533 is_constructible<_Tp, _Up&&>,
534 is_convertible<_Up&&, _Tp>,
535 __not_<__converts_from_optional<_Tp, _Up>>
536 >::value, bool> = true>
537 constexpr optional(optional<_Up>&& __t)
538 {
539 if (__t)
540 emplace(std::move(*__t));
541 }
542
543 template <typename _Up,
544 enable_if_t<__and_<
545 __not_<is_same<_Tp, _Up>>,
546 is_constructible<_Tp, _Up&&>,
547 __not_<is_convertible<_Up&&, _Tp>>,
548 __not_<__converts_from_optional<_Tp, _Up>>
549 >::value, bool> = false>
550 explicit constexpr optional(optional<_Up>&& __t)
551 {
552 if (__t)
553 emplace(std::move(*__t));
554 }
555
556 template<typename... _Args,
557 enable_if_t<is_constructible_v<_Tp, _Args&&...>, bool> = false>
558 explicit constexpr optional(in_place_t, _Args&&... __args)
559 : _Base(std::in_place, std::forward<_Args>(__args)...) { }
560
561 template<typename _Up, typename... _Args,
562 enable_if_t<is_constructible_v<_Tp,
563 initializer_list<_Up>&,
564 _Args&&...>, bool> = false>
565 explicit constexpr optional(in_place_t,
566 initializer_list<_Up> __il,
567 _Args&&... __args)
568 : _Base(std::in_place, __il, std::forward<_Args>(__args)...) { }
569
570 // Assignment operators.
571 optional&
572 operator=(nullopt_t) noexcept
573 {
574 this->_M_reset();
575 return *this;
576 }
577
578 template<typename _Up = _Tp>
579 enable_if_t<__and_<
580 __not_<is_same<optional<_Tp>, decay_t<_Up>>>,
581 is_constructible<_Tp, _Up>,
582 __not_<__and_<is_scalar<_Tp>,
583 is_same<_Tp, decay_t<_Up>>>>,
584 is_assignable<_Tp&, _Up>>::value,
585 optional&>
586 operator=(_Up&& __u)
587 {
588 if (this->_M_is_engaged())
589 this->_M_get() = std::forward<_Up>(__u);
590 else
591 this->_M_construct(std::forward<_Up>(__u));
592
593 return *this;
594 }
595
596 template<typename _Up>
597 enable_if_t<__and_<
598 __not_<is_same<_Tp, _Up>>,
599 is_constructible<_Tp, const _Up&>,
600 is_assignable<_Tp&, _Up>,
601 __not_<__converts_from_optional<_Tp, _Up>>,
602 __not_<__assigns_from_optional<_Tp, _Up>>
603 >::value,
604 optional&>
605 operator=(const optional<_Up>& __u)
606 {
607 if (__u)
608 {
609 if (this->_M_is_engaged())
610 this->_M_get() = *__u;
611 else
612 this->_M_construct(*__u);
613 }
614 else
615 {
616 this->_M_reset();
617 }
618 return *this;
619 }
620
621 template<typename _Up>
622 enable_if_t<__and_<
623 __not_<is_same<_Tp, _Up>>,
624 is_constructible<_Tp, _Up>,
625 is_assignable<_Tp&, _Up>,
626 __not_<__converts_from_optional<_Tp, _Up>>,
627 __not_<__assigns_from_optional<_Tp, _Up>>
628 >::value,
629 optional&>
630 operator=(optional<_Up>&& __u)
631 {
632 if (__u)
633 {
634 if (this->_M_is_engaged())
635 this->_M_get() = std::move(*__u);
636 else
637 this->_M_construct(std::move(*__u));
638 }
639 else
640 {
641 this->_M_reset();
642 }
643
644 return *this;
645 }
646
647 template<typename... _Args>
648 enable_if_t<is_constructible<_Tp, _Args&&...>::value, _Tp&>
649 emplace(_Args&&... __args)
650 {
651 this->_M_reset();
652 this->_M_construct(std::forward<_Args>(__args)...);
653 return this->_M_get();
654 }
655
656 template<typename _Up, typename... _Args>
657 enable_if_t<is_constructible<_Tp, initializer_list<_Up>&,
658 _Args&&...>::value, _Tp&>
659 emplace(initializer_list<_Up> __il, _Args&&... __args)
660 {
661 this->_M_reset();
662 this->_M_construct(__il, std::forward<_Args>(__args)...);
663 return this->_M_get();
664 }
665
666 // Destructor is implicit, implemented in _Optional_base.
667
668 // Swap.
669 void
670 swap(optional& __other)
671 noexcept(is_nothrow_move_constructible<_Tp>()
672 && is_nothrow_swappable_v<_Tp>)
673 {
674 using std::swap;
675
676 if (this->_M_is_engaged() && __other._M_is_engaged())
677 swap(this->_M_get(), __other._M_get());
678 else if (this->_M_is_engaged())
679 {
680 __other._M_construct(std::move(this->_M_get()));
681 this->_M_destruct();
682 }
683 else if (__other._M_is_engaged())
684 {
685 this->_M_construct(std::move(__other._M_get()));
686 __other._M_destruct();
687 }
688 }
689
690 // Observers.
691 constexpr const _Tp*
692 operator->() const
693 { return std::__addressof(this->_M_get()); }
694
695 _Tp*
696 operator->()
697 { return std::__addressof(this->_M_get()); }
698
699 constexpr const _Tp&
700 operator*() const&
701 { return this->_M_get(); }
702
703 constexpr _Tp&
704 operator*()&
705 { return this->_M_get(); }
706
707 constexpr _Tp&&
708 operator*()&&
709 { return std::move(this->_M_get()); }
710
711 constexpr const _Tp&&
712 operator*() const&&
713 { return std::move(this->_M_get()); }
714
715 constexpr explicit operator bool() const noexcept
716 { return this->_M_is_engaged(); }
717
718 constexpr bool has_value() const noexcept
719 { return this->_M_is_engaged(); }
720
721 constexpr const _Tp&
722 value() const&
723 {
724 return this->_M_is_engaged()
725 ? this->_M_get()
726 : (__throw_bad_optional_access(),
727 this->_M_get());
728 }
729
730 constexpr _Tp&
731 value()&
732 {
733 return this->_M_is_engaged()
734 ? this->_M_get()
735 : (__throw_bad_optional_access(),
736 this->_M_get());
737 }
738
739 constexpr _Tp&&
740 value()&&
741 {
742 return this->_M_is_engaged()
743 ? std::move(this->_M_get())
744 : (__throw_bad_optional_access(),
745 std::move(this->_M_get()));
746 }
747
748 constexpr const _Tp&&
749 value() const&&
750 {
751 return this->_M_is_engaged()
752 ? std::move(this->_M_get())
753 : (__throw_bad_optional_access(),
754 std::move(this->_M_get()));
755 }
756
757 template<typename _Up>
758 constexpr _Tp
759 value_or(_Up&& __u) const&
760 {
761 static_assert(__and_<is_copy_constructible<_Tp>,
762 is_convertible<_Up&&, _Tp>>(),
763 "Cannot return value");
764
765 return this->_M_is_engaged()
766 ? this->_M_get()
767 : static_cast<_Tp>(std::forward<_Up>(__u));
768 }
769
770 template<typename _Up>
771 _Tp
772 value_or(_Up&& __u) &&
773 {
774 static_assert(__and_<is_move_constructible<_Tp>,
775 is_convertible<_Up&&, _Tp>>(),
776 "Cannot return value" );
777
778 return this->_M_is_engaged()
779 ? std::move(this->_M_get())
780 : static_cast<_Tp>(std::forward<_Up>(__u));
781 }
782 void reset() noexcept { this->_M_reset(); }
783 };
784
785 template<typename _Tp>
786 using __optional_relop_t =
787 enable_if_t<is_convertible<_Tp, bool>::value, bool>;
788
789 // Comparisons between optional values.
790 template<typename _Tp, typename _Up>
791 constexpr auto
792 operator==(const optional<_Tp>& __lhs, const optional<_Up>& __rhs)
793 -> __optional_relop_t<decltype(declval<_Tp>() == declval<_Up>())>
794 {
795 return static_cast<bool>(__lhs) == static_cast<bool>(__rhs)
796 && (!__lhs || *__lhs == *__rhs);
797 }
798
799 template<typename _Tp, typename _Up>
800 constexpr auto
801 operator!=(const optional<_Tp>& __lhs, const optional<_Up>& __rhs)
802 -> __optional_relop_t<decltype(declval<_Tp>() != declval<_Up>())>
803 {
804 return static_cast<bool>(__lhs) != static_cast<bool>(__rhs)
805 || (static_cast<bool>(__lhs) && *__lhs != *__rhs);
806 }
807
808 template<typename _Tp, typename _Up>
809 constexpr auto
810 operator<(const optional<_Tp>& __lhs, const optional<_Up>& __rhs)
811 -> __optional_relop_t<decltype(declval<_Tp>() < declval<_Up>())>
812 {
813 return static_cast<bool>(__rhs) && (!__lhs || *__lhs < *__rhs);
814 }
815
816 template<typename _Tp, typename _Up>
817 constexpr auto
818 operator>(const optional<_Tp>& __lhs, const optional<_Up>& __rhs)
819 -> __optional_relop_t<decltype(declval<_Tp>() > declval<_Up>())>
820 {
821 return static_cast<bool>(__lhs) && (!__rhs || *__lhs > *__rhs);
822 }
823
824 template<typename _Tp, typename _Up>
825 constexpr auto
826 operator<=(const optional<_Tp>& __lhs, const optional<_Up>& __rhs)
827 -> __optional_relop_t<decltype(declval<_Tp>() <= declval<_Up>())>
828 {
829 return !__lhs || (static_cast<bool>(__rhs) && *__lhs <= *__rhs);
830 }
831
832 template<typename _Tp, typename _Up>
833 constexpr auto
834 operator>=(const optional<_Tp>& __lhs, const optional<_Up>& __rhs)
835 -> __optional_relop_t<decltype(declval<_Tp>() >= declval<_Up>())>
836 {
837 return !__rhs || (static_cast<bool>(__lhs) && *__lhs >= *__rhs);
838 }
839
840 // Comparisons with nullopt.
841 template<typename _Tp>
842 constexpr bool
843 operator==(const optional<_Tp>& __lhs, nullopt_t) noexcept
844 { return !__lhs; }
845
846 template<typename _Tp>
847 constexpr bool
848 operator==(nullopt_t, const optional<_Tp>& __rhs) noexcept
849 { return !__rhs; }
850
851 template<typename _Tp>
852 constexpr bool
853 operator!=(const optional<_Tp>& __lhs, nullopt_t) noexcept
854 { return static_cast<bool>(__lhs); }
855
856 template<typename _Tp>
857 constexpr bool
858 operator!=(nullopt_t, const optional<_Tp>& __rhs) noexcept
859 { return static_cast<bool>(__rhs); }
860
861 template<typename _Tp>
862 constexpr bool
863 operator<(const optional<_Tp>& /* __lhs */, nullopt_t) noexcept
864 { return false; }
865
866 template<typename _Tp>
867 constexpr bool
868 operator<(nullopt_t, const optional<_Tp>& __rhs) noexcept
869 { return static_cast<bool>(__rhs); }
870
871 template<typename _Tp>
872 constexpr bool
873 operator>(const optional<_Tp>& __lhs, nullopt_t) noexcept
874 { return static_cast<bool>(__lhs); }
875
876 template<typename _Tp>
877 constexpr bool
878 operator>(nullopt_t, const optional<_Tp>& /* __rhs */) noexcept
879 { return false; }
880
881 template<typename _Tp>
882 constexpr bool
883 operator<=(const optional<_Tp>& __lhs, nullopt_t) noexcept
884 { return !__lhs; }
885
886 template<typename _Tp>
887 constexpr bool
888 operator<=(nullopt_t, const optional<_Tp>& /* __rhs */) noexcept
889 { return true; }
890
891 template<typename _Tp>
892 constexpr bool
893 operator>=(const optional<_Tp>& /* __lhs */, nullopt_t) noexcept
894 { return true; }
895
896 template<typename _Tp>
897 constexpr bool
898 operator>=(nullopt_t, const optional<_Tp>& __rhs) noexcept
899 { return !__rhs; }
900
901 // Comparisons with value type.
902 template<typename _Tp, typename _Up>
903 constexpr auto
904 operator==(const optional<_Tp>& __lhs, const _Up& __rhs)
905 -> __optional_relop_t<decltype(declval<_Tp>() == declval<_Up>())>
906 { return __lhs && *__lhs == __rhs; }
907
908 template<typename _Tp, typename _Up>
909 constexpr auto
910 operator==(const _Up& __lhs, const optional<_Tp>& __rhs)
911 -> __optional_relop_t<decltype(declval<_Up>() == declval<_Tp>())>
912 { return __rhs && __lhs == *__rhs; }
913
914 template<typename _Tp, typename _Up>
915 constexpr auto
916 operator!=(const optional<_Tp>& __lhs, const _Up& __rhs)
917 -> __optional_relop_t<decltype(declval<_Tp>() != declval<_Up>())>
918 { return !__lhs || *__lhs != __rhs; }
919
920 template<typename _Tp, typename _Up>
921 constexpr auto
922 operator!=(const _Up& __lhs, const optional<_Tp>& __rhs)
923 -> __optional_relop_t<decltype(declval<_Up>() != declval<_Tp>())>
924 { return !__rhs || __lhs != *__rhs; }
925
926 template<typename _Tp, typename _Up>
927 constexpr auto
928 operator<(const optional<_Tp>& __lhs, const _Up& __rhs)
929 -> __optional_relop_t<decltype(declval<_Tp>() < declval<_Up>())>
930 { return !__lhs || *__lhs < __rhs; }
931
932 template<typename _Tp, typename _Up>
933 constexpr auto
934 operator<(const _Up& __lhs, const optional<_Tp>& __rhs)
935 -> __optional_relop_t<decltype(declval<_Up>() < declval<_Tp>())>
936 { return __rhs && __lhs < *__rhs; }
937
938 template<typename _Tp, typename _Up>
939 constexpr auto
940 operator>(const optional<_Tp>& __lhs, const _Up& __rhs)
941 -> __optional_relop_t<decltype(declval<_Tp>() > declval<_Up>())>
942 { return __lhs && *__lhs > __rhs; }
943
944 template<typename _Tp, typename _Up>
945 constexpr auto
946 operator>(const _Up& __lhs, const optional<_Tp>& __rhs)
947 -> __optional_relop_t<decltype(declval<_Up>() > declval<_Tp>())>
948 { return !__rhs || __lhs > *__rhs; }
949
950 template<typename _Tp, typename _Up>
951 constexpr auto
952 operator<=(const optional<_Tp>& __lhs, const _Up& __rhs)
953 -> __optional_relop_t<decltype(declval<_Tp>() <= declval<_Up>())>
954 { return !__lhs || *__lhs <= __rhs; }
955
956 template<typename _Tp, typename _Up>
957 constexpr auto
958 operator<=(const _Up& __lhs, const optional<_Tp>& __rhs)
959 -> __optional_relop_t<decltype(declval<_Up>() <= declval<_Tp>())>
960 { return __rhs && __lhs <= *__rhs; }
961
962 template<typename _Tp, typename _Up>
963 constexpr auto
964 operator>=(const optional<_Tp>& __lhs, const _Up& __rhs)
965 -> __optional_relop_t<decltype(declval<_Tp>() >= declval<_Up>())>
966 { return __lhs && *__lhs >= __rhs; }
967
968 template<typename _Tp, typename _Up>
969 constexpr auto
970 operator>=(const _Up& __lhs, const optional<_Tp>& __rhs)
971 -> __optional_relop_t<decltype(declval<_Up>() >= declval<_Tp>())>
972 { return !__rhs || __lhs >= *__rhs; }
973
974 // Swap and creation functions.
975
976 // _GLIBCXX_RESOLVE_LIB_DEFECTS
977 // 2748. swappable traits for optionals
978 template<typename _Tp>
979 inline enable_if_t<is_move_constructible_v<_Tp> && is_swappable_v<_Tp>>
980 swap(optional<_Tp>& __lhs, optional<_Tp>& __rhs)
981 noexcept(noexcept(__lhs.swap(__rhs)))
982 { __lhs.swap(__rhs); }
983
984 template<typename _Tp>
985 enable_if_t<!(is_move_constructible_v<_Tp> && is_swappable_v<_Tp>)>
986 swap(optional<_Tp>&, optional<_Tp>&) = delete;
987
988 template<typename _Tp>
989 constexpr optional<decay_t<_Tp>>
990 make_optional(_Tp&& __t)
991 { return optional<decay_t<_Tp>> { std::forward<_Tp>(__t) }; }
992
993 template<typename _Tp, typename ..._Args>
994 constexpr optional<_Tp>
995 make_optional(_Args&&... __args)
996 { return optional<_Tp> { in_place, std::forward<_Args>(__args)... }; }
997
998 template<typename _Tp, typename _Up, typename ..._Args>
999 constexpr optional<_Tp>
1000 make_optional(initializer_list<_Up> __il, _Args&&... __args)
1001 { return optional<_Tp> { in_place, __il, std::forward<_Args>(__args)... }; }
1002
1003 // Hash.
1004
1005 template<typename _Tp, typename _Up = remove_const_t<_Tp>,
1006 bool = __poison_hash<_Up>::__enable_hash_call>
1007 struct __optional_hash_call_base
1008 {
1009 size_t
1010 operator()(const optional<_Tp>& __t) const
1011 noexcept(noexcept(hash<_Up>{}(*__t)))
1012 {
1013 // We pick an arbitrary hash for disengaged optionals which hopefully
1014 // usual values of _Tp won't typically hash to.
1015 constexpr size_t __magic_disengaged_hash = static_cast<size_t>(-3333);
1016 return __t ? hash<_Up>{}(*__t) : __magic_disengaged_hash;
1017 }
1018 };
1019
1020 template<typename _Tp, typename _Up>
1021 struct __optional_hash_call_base<_Tp, _Up, false> {};
1022
1023 template<typename _Tp>
1024 struct hash<optional<_Tp>>
1025 : private __poison_hash<remove_const_t<_Tp>>,
1026 public __optional_hash_call_base<_Tp>
1027 {
1028 using result_type = size_t;
1029 using argument_type = optional<_Tp>;
1030 };
1031
1032 /// @}
1033
1034#if __cpp_deduction_guides >= 201606
1035 template <typename _Tp> optional(_Tp) -> optional<_Tp>;
1036#endif
1037
1038_GLIBCXX_END_NAMESPACE_VERSION
1039} // namespace std
1040
1041#endif // C++17
1042
1043#endif // _GLIBCXX_OPTIONAL
1044