]> git.ipfire.org Git - thirdparty/gcc.git/blob - libstdc++-v3/include/std/optional
Update copyright years.
[thirdparty/gcc.git] / libstdc++-v3 / include / std / optional
1 // <optional> -*- C++ -*-
2
3 // Copyright (C) 2013-2020 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 <exception>
39 #include <new>
40 #include <initializer_list>
41 #include <bits/exception_defines.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 #define __cpp_lib_optional 201606L
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
86 virtual const char* what() const noexcept override
87 { return "bad optional access"; }
88
89 virtual ~bad_optional_access() noexcept = default;
90 };
91
92 void
93 __throw_bad_optional_access()
94 __attribute__((__noreturn__));
95
96 // XXX Does not belong here.
97 inline void
98 __throw_bad_optional_access()
99 { _GLIBCXX_THROW_OR_ABORT(bad_optional_access()); }
100
101 // This class template manages construction/destruction of
102 // the contained value for a std::optional.
103 template <typename _Tp>
104 struct _Optional_payload_base
105 {
106 using _Stored_type = remove_const_t<_Tp>;
107
108 _Optional_payload_base() = default;
109 ~_Optional_payload_base() = default;
110
111 template<typename... _Args>
112 constexpr
113 _Optional_payload_base(in_place_t __tag, _Args&&... __args)
114 : _M_payload(__tag, std::forward<_Args>(__args)...),
115 _M_engaged(true)
116 { }
117
118 template<typename _Up, typename... _Args>
119 constexpr
120 _Optional_payload_base(std::initializer_list<_Up> __il,
121 _Args&&... __args)
122 : _M_payload(__il, std::forward<_Args>(__args)...),
123 _M_engaged(true)
124 { }
125
126 // Constructor used by _Optional_base copy constructor when the
127 // contained value is not trivially copy constructible.
128 constexpr
129 _Optional_payload_base(bool __engaged,
130 const _Optional_payload_base& __other)
131 {
132 if (__other._M_engaged)
133 this->_M_construct(__other._M_get());
134 }
135
136 // Constructor used by _Optional_base move constructor when the
137 // contained value is not trivially move constructible.
138 constexpr
139 _Optional_payload_base(bool __engaged,
140 _Optional_payload_base&& __other)
141 {
142 if (__other._M_engaged)
143 this->_M_construct(std::move(__other._M_get()));
144 }
145
146 // Copy constructor is only used to when the contained value is
147 // trivially copy constructible.
148 _Optional_payload_base(const _Optional_payload_base&) = default;
149
150 // Move constructor is only used to when the contained value is
151 // trivially copy constructible.
152 _Optional_payload_base(_Optional_payload_base&&) = default;
153
154 _Optional_payload_base&
155 operator=(const _Optional_payload_base&) = default;
156
157 _Optional_payload_base&
158 operator=(_Optional_payload_base&&) = default;
159
160 // used to perform non-trivial copy assignment.
161 constexpr void
162 _M_copy_assign(const _Optional_payload_base& __other)
163 {
164 if (this->_M_engaged && __other._M_engaged)
165 this->_M_get() = __other._M_get();
166 else
167 {
168 if (__other._M_engaged)
169 this->_M_construct(__other._M_get());
170 else
171 this->_M_reset();
172 }
173 }
174
175 // used to perform non-trivial move assignment.
176 constexpr void
177 _M_move_assign(_Optional_payload_base&& __other)
178 noexcept(__and_v<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 }
191
192 struct _Empty_byte { };
193
194 template<typename _Up, bool = is_trivially_destructible_v<_Up>>
195 union _Storage
196 {
197 constexpr _Storage() noexcept : _M_empty() { }
198
199 template<typename... _Args>
200 constexpr
201 _Storage(in_place_t, _Args&&... __args)
202 : _M_value(std::forward<_Args>(__args)...)
203 { }
204
205 template<typename _Vp, typename... _Args>
206 constexpr
207 _Storage(std::initializer_list<_Vp> __il, _Args&&... __args)
208 : _M_value(__il, std::forward<_Args>(__args)...)
209 { }
210
211 _Empty_byte _M_empty;
212 _Up _M_value;
213 };
214
215 template<typename _Up>
216 union _Storage<_Up, false>
217 {
218 constexpr _Storage() noexcept : _M_empty() { }
219
220 template<typename... _Args>
221 constexpr
222 _Storage(in_place_t, _Args&&... __args)
223 : _M_value(std::forward<_Args>(__args)...)
224 { }
225
226 template<typename _Vp, typename... _Args>
227 constexpr
228 _Storage(std::initializer_list<_Vp> __il, _Args&&... __args)
229 : _M_value(__il, std::forward<_Args>(__args)...)
230 { }
231
232 // User-provided destructor is needed when _Up has non-trivial dtor.
233 ~_Storage() { }
234
235 _Empty_byte _M_empty;
236 _Up _M_value;
237 };
238
239 _Storage<_Stored_type> _M_payload;
240
241 bool _M_engaged = false;
242
243 template<typename... _Args>
244 void
245 _M_construct(_Args&&... __args)
246 noexcept(is_nothrow_constructible_v<_Stored_type, _Args...>)
247 {
248 ::new ((void *) std::__addressof(this->_M_payload))
249 _Stored_type(std::forward<_Args>(__args)...);
250 this->_M_engaged = true;
251 }
252
253 constexpr void
254 _M_destroy() noexcept
255 {
256 _M_engaged = false;
257 _M_payload._M_value.~_Stored_type();
258 }
259
260 // The _M_get() operations have _M_engaged as a precondition.
261 // They exist to access the contained value with the appropriate
262 // const-qualification, because _M_payload has had the const removed.
263
264 constexpr _Tp&
265 _M_get() noexcept
266 { return this->_M_payload._M_value; }
267
268 constexpr const _Tp&
269 _M_get() const noexcept
270 { return this->_M_payload._M_value; }
271
272 // _M_reset is a 'safe' operation with no precondition.
273 constexpr void
274 _M_reset() noexcept
275 {
276 if (this->_M_engaged)
277 _M_destroy();
278 }
279 };
280
281 // Class template that manages the payload for optionals.
282 template <typename _Tp,
283 bool /*_HasTrivialDestructor*/ =
284 is_trivially_destructible_v<_Tp>,
285 bool /*_HasTrivialCopy */ =
286 is_trivially_copy_assignable_v<_Tp>
287 && is_trivially_copy_constructible_v<_Tp>,
288 bool /*_HasTrivialMove */ =
289 is_trivially_move_assignable_v<_Tp>
290 && is_trivially_move_constructible_v<_Tp>>
291 struct _Optional_payload;
292
293 // Payload for potentially-constexpr optionals (trivial copy/move/destroy).
294 template <typename _Tp>
295 struct _Optional_payload<_Tp, true, true, true>
296 : _Optional_payload_base<_Tp>
297 {
298 using _Optional_payload_base<_Tp>::_Optional_payload_base;
299
300 _Optional_payload() = default;
301 };
302
303 // Payload for optionals with non-trivial copy construction/assignment.
304 template <typename _Tp>
305 struct _Optional_payload<_Tp, true, false, true>
306 : _Optional_payload_base<_Tp>
307 {
308 using _Optional_payload_base<_Tp>::_Optional_payload_base;
309
310 _Optional_payload() = default;
311 ~_Optional_payload() = default;
312 _Optional_payload(const _Optional_payload&) = default;
313 _Optional_payload(_Optional_payload&&) = default;
314 _Optional_payload& operator=(_Optional_payload&&) = default;
315
316 // Non-trivial copy assignment.
317 constexpr
318 _Optional_payload&
319 operator=(const _Optional_payload& __other)
320 {
321 this->_M_copy_assign(__other);
322 return *this;
323 }
324 };
325
326 // Payload for optionals with non-trivial move construction/assignment.
327 template <typename _Tp>
328 struct _Optional_payload<_Tp, true, true, false>
329 : _Optional_payload_base<_Tp>
330 {
331 using _Optional_payload_base<_Tp>::_Optional_payload_base;
332
333 _Optional_payload() = default;
334 ~_Optional_payload() = default;
335 _Optional_payload(const _Optional_payload&) = default;
336 _Optional_payload(_Optional_payload&&) = default;
337 _Optional_payload& operator=(const _Optional_payload&) = default;
338
339 // Non-trivial move assignment.
340 constexpr
341 _Optional_payload&
342 operator=(_Optional_payload&& __other)
343 noexcept(__and_v<is_nothrow_move_constructible<_Tp>,
344 is_nothrow_move_assignable<_Tp>>)
345 {
346 this->_M_move_assign(std::move(__other));
347 return *this;
348 }
349 };
350
351 // Payload for optionals with non-trivial copy and move assignment.
352 template <typename _Tp>
353 struct _Optional_payload<_Tp, true, false, false>
354 : _Optional_payload_base<_Tp>
355 {
356 using _Optional_payload_base<_Tp>::_Optional_payload_base;
357
358 _Optional_payload() = default;
359 ~_Optional_payload() = default;
360 _Optional_payload(const _Optional_payload&) = default;
361 _Optional_payload(_Optional_payload&&) = default;
362
363 // Non-trivial copy assignment.
364 constexpr
365 _Optional_payload&
366 operator=(const _Optional_payload& __other)
367 {
368 this->_M_copy_assign(__other);
369 return *this;
370 }
371
372 // Non-trivial move assignment.
373 constexpr
374 _Optional_payload&
375 operator=(_Optional_payload&& __other)
376 noexcept(__and_v<is_nothrow_move_constructible<_Tp>,
377 is_nothrow_move_assignable<_Tp>>)
378 {
379 this->_M_move_assign(std::move(__other));
380 return *this;
381 }
382 };
383
384 // Payload for optionals with non-trivial destructors.
385 template <typename _Tp, bool _Copy, bool _Move>
386 struct _Optional_payload<_Tp, false, _Copy, _Move>
387 : _Optional_payload<_Tp, true, false, false>
388 {
389 // Base class implements all the constructors and assignment operators:
390 using _Optional_payload<_Tp, true, false, false>::_Optional_payload;
391 _Optional_payload() = default;
392 _Optional_payload(const _Optional_payload&) = default;
393 _Optional_payload(_Optional_payload&&) = default;
394 _Optional_payload& operator=(const _Optional_payload&) = default;
395 _Optional_payload& operator=(_Optional_payload&&) = default;
396
397 // Destructor needs to destroy the contained value:
398 ~_Optional_payload() { this->_M_reset(); }
399 };
400
401 // Common base class for _Optional_base<T> to avoid repeating these
402 // member functions in each specialization.
403 template<typename _Tp, typename _Dp>
404 class _Optional_base_impl
405 {
406 protected:
407 using _Stored_type = remove_const_t<_Tp>;
408
409 // The _M_construct operation has !_M_engaged as a precondition
410 // while _M_destruct has _M_engaged as a precondition.
411 template<typename... _Args>
412 void
413 _M_construct(_Args&&... __args)
414 noexcept(is_nothrow_constructible_v<_Stored_type, _Args...>)
415 {
416 ::new
417 (std::__addressof(static_cast<_Dp*>(this)->_M_payload._M_payload))
418 _Stored_type(std::forward<_Args>(__args)...);
419 static_cast<_Dp*>(this)->_M_payload._M_engaged = true;
420 }
421
422 void
423 _M_destruct() noexcept
424 { static_cast<_Dp*>(this)->_M_payload._M_destroy(); }
425
426 // _M_reset is a 'safe' operation with no precondition.
427 constexpr void
428 _M_reset() noexcept
429 { static_cast<_Dp*>(this)->_M_payload._M_reset(); }
430
431 constexpr bool _M_is_engaged() const noexcept
432 { return static_cast<const _Dp*>(this)->_M_payload._M_engaged; }
433
434 // The _M_get operations have _M_engaged as a precondition.
435 constexpr _Tp&
436 _M_get() noexcept
437 {
438 __glibcxx_assert(this->_M_is_engaged());
439 return static_cast<_Dp*>(this)->_M_payload._M_get();
440 }
441
442 constexpr const _Tp&
443 _M_get() const noexcept
444 {
445 __glibcxx_assert(this->_M_is_engaged());
446 return static_cast<const _Dp*>(this)->_M_payload._M_get();
447 }
448 };
449
450 /**
451 * @brief Class template that provides copy/move constructors of optional.
452 *
453 * Such a separate base class template is necessary in order to
454 * conditionally make copy/move constructors trivial.
455 *
456 * When the contained value is trivally copy/move constructible,
457 * the copy/move constructors of _Optional_base will invoke the
458 * trivial copy/move constructor of _Optional_payload. Otherwise,
459 * they will invoke _Optional_payload(bool, const _Optional_payload&)
460 * or _Optional_payload(bool, _Optional_payload&&) to initialize
461 * the contained value, if copying/moving an engaged optional.
462 *
463 * Whether the other special members are trivial is determined by the
464 * _Optional_payload<_Tp> specialization used for the _M_payload member.
465 *
466 * @see optional, _Enable_special_members
467 */
468 template<typename _Tp,
469 bool = is_trivially_copy_constructible_v<_Tp>,
470 bool = is_trivially_move_constructible_v<_Tp>>
471 struct _Optional_base
472 : _Optional_base_impl<_Tp, _Optional_base<_Tp>>
473 {
474 // Constructors for disengaged optionals.
475 constexpr _Optional_base() = default;
476
477 // Constructors for engaged optionals.
478 template<typename... _Args,
479 enable_if_t<is_constructible_v<_Tp, _Args&&...>, bool> = false>
480 constexpr explicit _Optional_base(in_place_t, _Args&&... __args)
481 : _M_payload(in_place,
482 std::forward<_Args>(__args)...) { }
483
484 template<typename _Up, typename... _Args,
485 enable_if_t<is_constructible_v<_Tp,
486 initializer_list<_Up>&,
487 _Args&&...>, bool> = false>
488 constexpr explicit _Optional_base(in_place_t,
489 initializer_list<_Up> __il,
490 _Args&&... __args)
491 : _M_payload(in_place,
492 __il, std::forward<_Args>(__args)...)
493 { }
494
495 // Copy and move constructors.
496 constexpr _Optional_base(const _Optional_base& __other)
497 : _M_payload(__other._M_payload._M_engaged,
498 __other._M_payload)
499 { }
500
501 constexpr _Optional_base(_Optional_base&& __other)
502 noexcept(is_nothrow_move_constructible_v<_Tp>)
503 : _M_payload(__other._M_payload._M_engaged,
504 std::move(__other._M_payload))
505 { }
506
507 // Assignment operators.
508 _Optional_base& operator=(const _Optional_base&) = default;
509 _Optional_base& operator=(_Optional_base&&) = default;
510
511 _Optional_payload<_Tp> _M_payload;
512 };
513
514 template<typename _Tp>
515 struct _Optional_base<_Tp, false, true>
516 : _Optional_base_impl<_Tp, _Optional_base<_Tp>>
517 {
518 // Constructors for disengaged optionals.
519 constexpr _Optional_base() = default;
520
521 // Constructors for engaged optionals.
522 template<typename... _Args,
523 enable_if_t<is_constructible_v<_Tp, _Args&&...>, bool> = false>
524 constexpr explicit _Optional_base(in_place_t, _Args&&... __args)
525 : _M_payload(in_place,
526 std::forward<_Args>(__args)...) { }
527
528 template<typename _Up, typename... _Args,
529 enable_if_t<is_constructible_v<_Tp,
530 initializer_list<_Up>&,
531 _Args&&...>, bool> = false>
532 constexpr explicit _Optional_base(in_place_t,
533 initializer_list<_Up> __il,
534 _Args&&... __args)
535 : _M_payload(in_place,
536 __il, std::forward<_Args>(__args)...)
537 { }
538
539 // Copy and move constructors.
540 constexpr _Optional_base(const _Optional_base& __other)
541 : _M_payload(__other._M_payload._M_engaged,
542 __other._M_payload)
543 { }
544
545 constexpr _Optional_base(_Optional_base&& __other) = default;
546
547 // Assignment operators.
548 _Optional_base& operator=(const _Optional_base&) = default;
549 _Optional_base& operator=(_Optional_base&&) = default;
550
551 _Optional_payload<_Tp> _M_payload;
552 };
553
554 template<typename _Tp>
555 struct _Optional_base<_Tp, true, false>
556 : _Optional_base_impl<_Tp, _Optional_base<_Tp>>
557 {
558 // Constructors for disengaged optionals.
559 constexpr _Optional_base() = default;
560
561 // Constructors for engaged optionals.
562 template<typename... _Args,
563 enable_if_t<is_constructible_v<_Tp, _Args&&...>, bool> = false>
564 constexpr explicit _Optional_base(in_place_t, _Args&&... __args)
565 : _M_payload(in_place,
566 std::forward<_Args>(__args)...) { }
567
568 template<typename _Up, typename... _Args,
569 enable_if_t<is_constructible_v<_Tp,
570 initializer_list<_Up>&,
571 _Args&&...>, bool> = false>
572 constexpr explicit _Optional_base(in_place_t,
573 initializer_list<_Up> __il,
574 _Args&&... __args)
575 : _M_payload(in_place,
576 __il, std::forward<_Args>(__args)...)
577 { }
578
579 // Copy and move constructors.
580 constexpr _Optional_base(const _Optional_base& __other) = default;
581
582 constexpr _Optional_base(_Optional_base&& __other)
583 noexcept(is_nothrow_move_constructible_v<_Tp>)
584 : _M_payload(__other._M_payload._M_engaged,
585 std::move(__other._M_payload))
586 { }
587
588 // Assignment operators.
589 _Optional_base& operator=(const _Optional_base&) = default;
590 _Optional_base& operator=(_Optional_base&&) = default;
591
592 _Optional_payload<_Tp> _M_payload;
593 };
594
595 template<typename _Tp>
596 struct _Optional_base<_Tp, true, true>
597 : _Optional_base_impl<_Tp, _Optional_base<_Tp>>
598 {
599 // Constructors for disengaged optionals.
600 constexpr _Optional_base() = default;
601
602 // Constructors for engaged optionals.
603 template<typename... _Args,
604 enable_if_t<is_constructible_v<_Tp, _Args&&...>, bool> = false>
605 constexpr explicit _Optional_base(in_place_t, _Args&&... __args)
606 : _M_payload(in_place,
607 std::forward<_Args>(__args)...) { }
608
609 template<typename _Up, typename... _Args,
610 enable_if_t<is_constructible_v<_Tp,
611 initializer_list<_Up>&,
612 _Args&&...>, bool> = false>
613 constexpr explicit _Optional_base(in_place_t,
614 initializer_list<_Up> __il,
615 _Args&&... __args)
616 : _M_payload(in_place,
617 __il, std::forward<_Args>(__args)...)
618 { }
619
620 // Copy and move constructors.
621 constexpr _Optional_base(const _Optional_base& __other) = default;
622 constexpr _Optional_base(_Optional_base&& __other) = default;
623
624 // Assignment operators.
625 _Optional_base& operator=(const _Optional_base&) = default;
626 _Optional_base& operator=(_Optional_base&&) = default;
627
628 _Optional_payload<_Tp> _M_payload;
629 };
630
631 template<typename _Tp>
632 class optional;
633
634 template<typename _Tp, typename _Up>
635 using __converts_from_optional =
636 __or_<is_constructible<_Tp, const optional<_Up>&>,
637 is_constructible<_Tp, optional<_Up>&>,
638 is_constructible<_Tp, const optional<_Up>&&>,
639 is_constructible<_Tp, optional<_Up>&&>,
640 is_convertible<const optional<_Up>&, _Tp>,
641 is_convertible<optional<_Up>&, _Tp>,
642 is_convertible<const optional<_Up>&&, _Tp>,
643 is_convertible<optional<_Up>&&, _Tp>>;
644
645 template<typename _Tp, typename _Up>
646 using __assigns_from_optional =
647 __or_<is_assignable<_Tp&, const optional<_Up>&>,
648 is_assignable<_Tp&, optional<_Up>&>,
649 is_assignable<_Tp&, const optional<_Up>&&>,
650 is_assignable<_Tp&, optional<_Up>&&>>;
651
652 /**
653 * @brief Class template for optional values.
654 */
655 template<typename _Tp>
656 class optional
657 : private _Optional_base<_Tp>,
658 private _Enable_copy_move<
659 // Copy constructor.
660 is_copy_constructible_v<_Tp>,
661 // Copy assignment.
662 __and_v<is_copy_constructible<_Tp>, is_copy_assignable<_Tp>>,
663 // Move constructor.
664 is_move_constructible_v<_Tp>,
665 // Move assignment.
666 __and_v<is_move_constructible<_Tp>, is_move_assignable<_Tp>>,
667 // Unique tag type.
668 optional<_Tp>>
669 {
670 static_assert(!is_same_v<remove_cv_t<_Tp>, nullopt_t>);
671 static_assert(!is_same_v<remove_cv_t<_Tp>, in_place_t>);
672 static_assert(!is_reference_v<_Tp>);
673
674 private:
675 using _Base = _Optional_base<_Tp>;
676
677 // SFINAE helpers
678 template<typename _Up>
679 using __not_self = __not_<is_same<optional, __remove_cvref_t<_Up>>>;
680 template<typename _Up>
681 using __not_tag = __not_<is_same<in_place_t, __remove_cvref_t<_Up>>>;
682 template<typename... _Cond>
683 using _Requires = enable_if_t<__and_v<_Cond...>, bool>;
684
685 public:
686 using value_type = _Tp;
687
688 constexpr optional() = default;
689
690 constexpr optional(nullopt_t) noexcept { }
691
692 // Converting constructors for engaged optionals.
693 template<typename _Up = _Tp,
694 _Requires<__not_self<_Up>, __not_tag<_Up>,
695 is_constructible<_Tp, _Up&&>,
696 is_convertible<_Up&&, _Tp>> = true>
697 constexpr
698 optional(_Up&& __t)
699 : _Base(std::in_place, std::forward<_Up>(__t)) { }
700
701 template<typename _Up = _Tp,
702 _Requires<__not_self<_Up>, __not_tag<_Up>,
703 is_constructible<_Tp, _Up&&>,
704 __not_<is_convertible<_Up&&, _Tp>>> = false>
705 explicit constexpr
706 optional(_Up&& __t)
707 : _Base(std::in_place, std::forward<_Up>(__t)) { }
708
709 template<typename _Up,
710 _Requires<__not_<is_same<_Tp, _Up>>,
711 is_constructible<_Tp, const _Up&>,
712 is_convertible<const _Up&, _Tp>,
713 __not_<__converts_from_optional<_Tp, _Up>>> = true>
714 constexpr
715 optional(const optional<_Up>& __t)
716 {
717 if (__t)
718 emplace(*__t);
719 }
720
721 template<typename _Up,
722 _Requires<__not_<is_same<_Tp, _Up>>,
723 is_constructible<_Tp, const _Up&>,
724 __not_<is_convertible<const _Up&, _Tp>>,
725 __not_<__converts_from_optional<_Tp, _Up>>> = false>
726 explicit constexpr
727 optional(const optional<_Up>& __t)
728 {
729 if (__t)
730 emplace(*__t);
731 }
732
733 template <typename _Up,
734 _Requires<__not_<is_same<_Tp, _Up>>,
735 is_constructible<_Tp, _Up&&>,
736 is_convertible<_Up&&, _Tp>,
737 __not_<__converts_from_optional<_Tp, _Up>>> = true>
738 constexpr
739 optional(optional<_Up>&& __t)
740 {
741 if (__t)
742 emplace(std::move(*__t));
743 }
744
745 template <typename _Up,
746 _Requires<__not_<is_same<_Tp, _Up>>,
747 is_constructible<_Tp, _Up&&>,
748 __not_<is_convertible<_Up&&, _Tp>>,
749 __not_<__converts_from_optional<_Tp, _Up>>> = false>
750 explicit constexpr
751 optional(optional<_Up>&& __t)
752 {
753 if (__t)
754 emplace(std::move(*__t));
755 }
756
757 template<typename... _Args,
758 _Requires<is_constructible<_Tp, _Args&&...>> = false>
759 explicit constexpr
760 optional(in_place_t, _Args&&... __args)
761 : _Base(std::in_place, std::forward<_Args>(__args)...) { }
762
763 template<typename _Up, typename... _Args,
764 _Requires<is_constructible<_Tp,
765 initializer_list<_Up>&,
766 _Args&&...>> = false>
767 explicit constexpr
768 optional(in_place_t, initializer_list<_Up> __il, _Args&&... __args)
769 : _Base(std::in_place, __il, std::forward<_Args>(__args)...) { }
770
771 // Assignment operators.
772 optional&
773 operator=(nullopt_t) noexcept
774 {
775 this->_M_reset();
776 return *this;
777 }
778
779 template<typename _Up = _Tp>
780 enable_if_t<__and_v<__not_self<_Up>,
781 __not_<__and_<is_scalar<_Tp>,
782 is_same<_Tp, decay_t<_Up>>>>,
783 is_constructible<_Tp, _Up>,
784 is_assignable<_Tp&, _Up>>,
785 optional&>
786 operator=(_Up&& __u)
787 {
788 if (this->_M_is_engaged())
789 this->_M_get() = std::forward<_Up>(__u);
790 else
791 this->_M_construct(std::forward<_Up>(__u));
792
793 return *this;
794 }
795
796 template<typename _Up>
797 enable_if_t<__and_v<__not_<is_same<_Tp, _Up>>,
798 is_constructible<_Tp, const _Up&>,
799 is_assignable<_Tp&, _Up>,
800 __not_<__converts_from_optional<_Tp, _Up>>,
801 __not_<__assigns_from_optional<_Tp, _Up>>>,
802 optional&>
803 operator=(const optional<_Up>& __u)
804 {
805 if (__u)
806 {
807 if (this->_M_is_engaged())
808 this->_M_get() = *__u;
809 else
810 this->_M_construct(*__u);
811 }
812 else
813 {
814 this->_M_reset();
815 }
816 return *this;
817 }
818
819 template<typename _Up>
820 enable_if_t<__and_v<__not_<is_same<_Tp, _Up>>,
821 is_constructible<_Tp, _Up>,
822 is_assignable<_Tp&, _Up>,
823 __not_<__converts_from_optional<_Tp, _Up>>,
824 __not_<__assigns_from_optional<_Tp, _Up>>>,
825 optional&>
826 operator=(optional<_Up>&& __u)
827 {
828 if (__u)
829 {
830 if (this->_M_is_engaged())
831 this->_M_get() = std::move(*__u);
832 else
833 this->_M_construct(std::move(*__u));
834 }
835 else
836 {
837 this->_M_reset();
838 }
839
840 return *this;
841 }
842
843 template<typename... _Args>
844 enable_if_t<is_constructible_v<_Tp, _Args&&...>, _Tp&>
845 emplace(_Args&&... __args)
846 {
847 this->_M_reset();
848 this->_M_construct(std::forward<_Args>(__args)...);
849 return this->_M_get();
850 }
851
852 template<typename _Up, typename... _Args>
853 enable_if_t<is_constructible_v<_Tp, initializer_list<_Up>&,
854 _Args&&...>, _Tp&>
855 emplace(initializer_list<_Up> __il, _Args&&... __args)
856 {
857 this->_M_reset();
858 this->_M_construct(__il, std::forward<_Args>(__args)...);
859 return this->_M_get();
860 }
861
862 // Destructor is implicit, implemented in _Optional_base.
863
864 // Swap.
865 void
866 swap(optional& __other)
867 noexcept(is_nothrow_move_constructible_v<_Tp>
868 && is_nothrow_swappable_v<_Tp>)
869 {
870 using std::swap;
871
872 if (this->_M_is_engaged() && __other._M_is_engaged())
873 swap(this->_M_get(), __other._M_get());
874 else if (this->_M_is_engaged())
875 {
876 __other._M_construct(std::move(this->_M_get()));
877 this->_M_destruct();
878 }
879 else if (__other._M_is_engaged())
880 {
881 this->_M_construct(std::move(__other._M_get()));
882 __other._M_destruct();
883 }
884 }
885
886 // Observers.
887 constexpr const _Tp*
888 operator->() const
889 { return std::__addressof(this->_M_get()); }
890
891 constexpr _Tp*
892 operator->()
893 { return std::__addressof(this->_M_get()); }
894
895 constexpr const _Tp&
896 operator*() const&
897 { return this->_M_get(); }
898
899 constexpr _Tp&
900 operator*()&
901 { return this->_M_get(); }
902
903 constexpr _Tp&&
904 operator*()&&
905 { return std::move(this->_M_get()); }
906
907 constexpr const _Tp&&
908 operator*() const&&
909 { return std::move(this->_M_get()); }
910
911 constexpr explicit operator bool() const noexcept
912 { return this->_M_is_engaged(); }
913
914 constexpr bool has_value() const noexcept
915 { return this->_M_is_engaged(); }
916
917 constexpr const _Tp&
918 value() const&
919 {
920 return this->_M_is_engaged()
921 ? this->_M_get()
922 : (__throw_bad_optional_access(), this->_M_get());
923 }
924
925 constexpr _Tp&
926 value()&
927 {
928 return this->_M_is_engaged()
929 ? this->_M_get()
930 : (__throw_bad_optional_access(), this->_M_get());
931 }
932
933 constexpr _Tp&&
934 value()&&
935 {
936 return this->_M_is_engaged()
937 ? std::move(this->_M_get())
938 : (__throw_bad_optional_access(), std::move(this->_M_get()));
939 }
940
941 constexpr const _Tp&&
942 value() const&&
943 {
944 return this->_M_is_engaged()
945 ? std::move(this->_M_get())
946 : (__throw_bad_optional_access(), std::move(this->_M_get()));
947 }
948
949 template<typename _Up>
950 constexpr _Tp
951 value_or(_Up&& __u) const&
952 {
953 static_assert(is_copy_constructible_v<_Tp>);
954 static_assert(is_convertible_v<_Up&&, _Tp>);
955
956 return this->_M_is_engaged()
957 ? this->_M_get() : static_cast<_Tp>(std::forward<_Up>(__u));
958 }
959
960 template<typename _Up>
961 constexpr _Tp
962 value_or(_Up&& __u) &&
963 {
964 static_assert(is_move_constructible_v<_Tp>);
965 static_assert(is_convertible_v<_Up&&, _Tp>);
966
967 return this->_M_is_engaged()
968 ? std::move(this->_M_get())
969 : static_cast<_Tp>(std::forward<_Up>(__u));
970 }
971
972 void reset() noexcept { this->_M_reset(); }
973 };
974
975 template<typename _Tp>
976 using __optional_relop_t =
977 enable_if_t<is_convertible<_Tp, bool>::value, bool>;
978
979 // Comparisons between optional values.
980 template<typename _Tp, typename _Up>
981 constexpr auto
982 operator==(const optional<_Tp>& __lhs, const optional<_Up>& __rhs)
983 -> __optional_relop_t<decltype(declval<_Tp>() == declval<_Up>())>
984 {
985 return static_cast<bool>(__lhs) == static_cast<bool>(__rhs)
986 && (!__lhs || *__lhs == *__rhs);
987 }
988
989 template<typename _Tp, typename _Up>
990 constexpr auto
991 operator!=(const optional<_Tp>& __lhs, const optional<_Up>& __rhs)
992 -> __optional_relop_t<decltype(declval<_Tp>() != declval<_Up>())>
993 {
994 return static_cast<bool>(__lhs) != static_cast<bool>(__rhs)
995 || (static_cast<bool>(__lhs) && *__lhs != *__rhs);
996 }
997
998 template<typename _Tp, typename _Up>
999 constexpr auto
1000 operator<(const optional<_Tp>& __lhs, const optional<_Up>& __rhs)
1001 -> __optional_relop_t<decltype(declval<_Tp>() < declval<_Up>())>
1002 {
1003 return static_cast<bool>(__rhs) && (!__lhs || *__lhs < *__rhs);
1004 }
1005
1006 template<typename _Tp, typename _Up>
1007 constexpr auto
1008 operator>(const optional<_Tp>& __lhs, const optional<_Up>& __rhs)
1009 -> __optional_relop_t<decltype(declval<_Tp>() > declval<_Up>())>
1010 {
1011 return static_cast<bool>(__lhs) && (!__rhs || *__lhs > *__rhs);
1012 }
1013
1014 template<typename _Tp, typename _Up>
1015 constexpr auto
1016 operator<=(const optional<_Tp>& __lhs, const optional<_Up>& __rhs)
1017 -> __optional_relop_t<decltype(declval<_Tp>() <= declval<_Up>())>
1018 {
1019 return !__lhs || (static_cast<bool>(__rhs) && *__lhs <= *__rhs);
1020 }
1021
1022 template<typename _Tp, typename _Up>
1023 constexpr auto
1024 operator>=(const optional<_Tp>& __lhs, const optional<_Up>& __rhs)
1025 -> __optional_relop_t<decltype(declval<_Tp>() >= declval<_Up>())>
1026 {
1027 return !__rhs || (static_cast<bool>(__lhs) && *__lhs >= *__rhs);
1028 }
1029
1030 // Comparisons with nullopt.
1031 template<typename _Tp>
1032 constexpr bool
1033 operator==(const optional<_Tp>& __lhs, nullopt_t) noexcept
1034 { return !__lhs; }
1035
1036 template<typename _Tp>
1037 constexpr bool
1038 operator==(nullopt_t, const optional<_Tp>& __rhs) noexcept
1039 { return !__rhs; }
1040
1041 template<typename _Tp>
1042 constexpr bool
1043 operator!=(const optional<_Tp>& __lhs, nullopt_t) noexcept
1044 { return static_cast<bool>(__lhs); }
1045
1046 template<typename _Tp>
1047 constexpr bool
1048 operator!=(nullopt_t, const optional<_Tp>& __rhs) noexcept
1049 { return static_cast<bool>(__rhs); }
1050
1051 template<typename _Tp>
1052 constexpr bool
1053 operator<(const optional<_Tp>& /* __lhs */, nullopt_t) noexcept
1054 { return false; }
1055
1056 template<typename _Tp>
1057 constexpr bool
1058 operator<(nullopt_t, const optional<_Tp>& __rhs) noexcept
1059 { return static_cast<bool>(__rhs); }
1060
1061 template<typename _Tp>
1062 constexpr bool
1063 operator>(const optional<_Tp>& __lhs, nullopt_t) noexcept
1064 { return static_cast<bool>(__lhs); }
1065
1066 template<typename _Tp>
1067 constexpr bool
1068 operator>(nullopt_t, const optional<_Tp>& /* __rhs */) noexcept
1069 { return false; }
1070
1071 template<typename _Tp>
1072 constexpr bool
1073 operator<=(const optional<_Tp>& __lhs, nullopt_t) noexcept
1074 { return !__lhs; }
1075
1076 template<typename _Tp>
1077 constexpr bool
1078 operator<=(nullopt_t, const optional<_Tp>& /* __rhs */) noexcept
1079 { return true; }
1080
1081 template<typename _Tp>
1082 constexpr bool
1083 operator>=(const optional<_Tp>& /* __lhs */, nullopt_t) noexcept
1084 { return true; }
1085
1086 template<typename _Tp>
1087 constexpr bool
1088 operator>=(nullopt_t, const optional<_Tp>& __rhs) noexcept
1089 { return !__rhs; }
1090
1091 // Comparisons with value type.
1092 template<typename _Tp, typename _Up>
1093 constexpr auto
1094 operator==(const optional<_Tp>& __lhs, const _Up& __rhs)
1095 -> __optional_relop_t<decltype(declval<_Tp>() == declval<_Up>())>
1096 { return __lhs && *__lhs == __rhs; }
1097
1098 template<typename _Tp, typename _Up>
1099 constexpr auto
1100 operator==(const _Up& __lhs, const optional<_Tp>& __rhs)
1101 -> __optional_relop_t<decltype(declval<_Up>() == declval<_Tp>())>
1102 { return __rhs && __lhs == *__rhs; }
1103
1104 template<typename _Tp, typename _Up>
1105 constexpr auto
1106 operator!=(const optional<_Tp>& __lhs, const _Up& __rhs)
1107 -> __optional_relop_t<decltype(declval<_Tp>() != declval<_Up>())>
1108 { return !__lhs || *__lhs != __rhs; }
1109
1110 template<typename _Tp, typename _Up>
1111 constexpr auto
1112 operator!=(const _Up& __lhs, const optional<_Tp>& __rhs)
1113 -> __optional_relop_t<decltype(declval<_Up>() != declval<_Tp>())>
1114 { return !__rhs || __lhs != *__rhs; }
1115
1116 template<typename _Tp, typename _Up>
1117 constexpr auto
1118 operator<(const optional<_Tp>& __lhs, const _Up& __rhs)
1119 -> __optional_relop_t<decltype(declval<_Tp>() < declval<_Up>())>
1120 { return !__lhs || *__lhs < __rhs; }
1121
1122 template<typename _Tp, typename _Up>
1123 constexpr auto
1124 operator<(const _Up& __lhs, const optional<_Tp>& __rhs)
1125 -> __optional_relop_t<decltype(declval<_Up>() < declval<_Tp>())>
1126 { return __rhs && __lhs < *__rhs; }
1127
1128 template<typename _Tp, typename _Up>
1129 constexpr auto
1130 operator>(const optional<_Tp>& __lhs, const _Up& __rhs)
1131 -> __optional_relop_t<decltype(declval<_Tp>() > declval<_Up>())>
1132 { return __lhs && *__lhs > __rhs; }
1133
1134 template<typename _Tp, typename _Up>
1135 constexpr auto
1136 operator>(const _Up& __lhs, const optional<_Tp>& __rhs)
1137 -> __optional_relop_t<decltype(declval<_Up>() > declval<_Tp>())>
1138 { return !__rhs || __lhs > *__rhs; }
1139
1140 template<typename _Tp, typename _Up>
1141 constexpr auto
1142 operator<=(const optional<_Tp>& __lhs, const _Up& __rhs)
1143 -> __optional_relop_t<decltype(declval<_Tp>() <= declval<_Up>())>
1144 { return !__lhs || *__lhs <= __rhs; }
1145
1146 template<typename _Tp, typename _Up>
1147 constexpr auto
1148 operator<=(const _Up& __lhs, const optional<_Tp>& __rhs)
1149 -> __optional_relop_t<decltype(declval<_Up>() <= declval<_Tp>())>
1150 { return __rhs && __lhs <= *__rhs; }
1151
1152 template<typename _Tp, typename _Up>
1153 constexpr auto
1154 operator>=(const optional<_Tp>& __lhs, const _Up& __rhs)
1155 -> __optional_relop_t<decltype(declval<_Tp>() >= declval<_Up>())>
1156 { return __lhs && *__lhs >= __rhs; }
1157
1158 template<typename _Tp, typename _Up>
1159 constexpr auto
1160 operator>=(const _Up& __lhs, const optional<_Tp>& __rhs)
1161 -> __optional_relop_t<decltype(declval<_Up>() >= declval<_Tp>())>
1162 { return !__rhs || __lhs >= *__rhs; }
1163
1164 // Swap and creation functions.
1165
1166 // _GLIBCXX_RESOLVE_LIB_DEFECTS
1167 // 2748. swappable traits for optionals
1168 template<typename _Tp>
1169 inline enable_if_t<is_move_constructible_v<_Tp> && is_swappable_v<_Tp>>
1170 swap(optional<_Tp>& __lhs, optional<_Tp>& __rhs)
1171 noexcept(noexcept(__lhs.swap(__rhs)))
1172 { __lhs.swap(__rhs); }
1173
1174 template<typename _Tp>
1175 enable_if_t<!(is_move_constructible_v<_Tp> && is_swappable_v<_Tp>)>
1176 swap(optional<_Tp>&, optional<_Tp>&) = delete;
1177
1178 template<typename _Tp>
1179 constexpr optional<decay_t<_Tp>>
1180 make_optional(_Tp&& __t)
1181 { return optional<decay_t<_Tp>> { std::forward<_Tp>(__t) }; }
1182
1183 template<typename _Tp, typename ..._Args>
1184 constexpr optional<_Tp>
1185 make_optional(_Args&&... __args)
1186 { return optional<_Tp> { in_place, std::forward<_Args>(__args)... }; }
1187
1188 template<typename _Tp, typename _Up, typename ..._Args>
1189 constexpr optional<_Tp>
1190 make_optional(initializer_list<_Up> __il, _Args&&... __args)
1191 { return optional<_Tp> { in_place, __il, std::forward<_Args>(__args)... }; }
1192
1193 // Hash.
1194
1195 template<typename _Tp, typename _Up = remove_const_t<_Tp>,
1196 bool = __poison_hash<_Up>::__enable_hash_call>
1197 struct __optional_hash_call_base
1198 {
1199 size_t
1200 operator()(const optional<_Tp>& __t) const
1201 noexcept(noexcept(hash<_Up>{}(*__t)))
1202 {
1203 // We pick an arbitrary hash for disengaged optionals which hopefully
1204 // usual values of _Tp won't typically hash to.
1205 constexpr size_t __magic_disengaged_hash = static_cast<size_t>(-3333);
1206 return __t ? hash<_Up>{}(*__t) : __magic_disengaged_hash;
1207 }
1208 };
1209
1210 template<typename _Tp, typename _Up>
1211 struct __optional_hash_call_base<_Tp, _Up, false> {};
1212
1213 template<typename _Tp>
1214 struct hash<optional<_Tp>>
1215 : private __poison_hash<remove_const_t<_Tp>>,
1216 public __optional_hash_call_base<_Tp>
1217 {
1218 using result_type [[__deprecated__]] = size_t;
1219 using argument_type [[__deprecated__]] = optional<_Tp>;
1220 };
1221
1222 template<typename _Tp>
1223 struct __is_fast_hash<hash<optional<_Tp>>> : __is_fast_hash<hash<_Tp>>
1224 { };
1225
1226 /// @}
1227
1228 #if __cpp_deduction_guides >= 201606
1229 template <typename _Tp> optional(_Tp) -> optional<_Tp>;
1230 #endif
1231
1232 _GLIBCXX_END_NAMESPACE_VERSION
1233 } // namespace std
1234
1235 #endif // C++17
1236
1237 #endif // _GLIBCXX_OPTIONAL