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