libstdc++
optional
Go to the documentation of this file.
1// <optional> -*- C++ -*-
2
3// Copyright (C) 2013-2025 Free Software Foundation, Inc.
4// Copyright The GNU Toolchain Authors.
5//
6// This file is part of the GNU ISO C++ Library. This library is free
7// software; you can redistribute it and/or modify it under the
8// terms of the GNU General Public License as published by the
9// Free Software Foundation; either version 3, or (at your option)
10// any later version.
11
12// This library is distributed in the hope that it will be useful,
13// but WITHOUT ANY WARRANTY; without even the implied warranty of
14// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15// GNU General Public License for more details.
16
17// Under Section 7 of GPL version 3, you are granted additional
18// permissions described in the GCC Runtime Library Exception, version
19// 3.1, as published by the Free Software Foundation.
20
21// You should have received a copy of the GNU General Public License and
22// a copy of the GCC Runtime Library Exception along with this program;
23// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
24// <http://www.gnu.org/licenses/>.
25
26/** @file include/optional
27 * This is a Standard C++ Library header.
28 */
29
30#ifndef _GLIBCXX_OPTIONAL
31#define _GLIBCXX_OPTIONAL 1
32
33#ifdef _GLIBCXX_SYSHDR
34#pragma GCC system_header
35#endif
36
37#define __glibcxx_want_freestanding_optional
38#define __glibcxx_want_optional
39#define __glibcxx_want_optional_range_support
40#define __glibcxx_want_constrained_equality
41#include <bits/version.h>
42
43#ifdef __cpp_lib_optional // C++ >= 17
44
45#include <type_traits>
46#include <exception>
47#include <new>
48#include <initializer_list>
49#include <bits/enable_special_members.h>
50#include <bits/exception_defines.h>
51#include <bits/functional_hash.h>
52#include <bits/stl_construct.h> // _Construct
53#include <bits/utility.h> // in_place_t
54#if __cplusplus > 201703L
55# include <compare>
56# include <bits/invoke.h> // std::__invoke
57#endif
58#if __cplusplus > 202002L
59# include <concepts>
60#endif
61#ifdef __cpp_lib_optional_range_support // C++ >= 26
62# include <bits/formatfwd.h>
63# include <bits/ranges_base.h>
64# include <bits/stl_iterator.h>
65#endif
66
67namespace std _GLIBCXX_VISIBILITY(default)
68{
69_GLIBCXX_BEGIN_NAMESPACE_VERSION
70
71 /**
72 * @addtogroup utilities
73 * @{
74 */
75
76 template<typename _Tp>
77 class optional;
78
79 /// Tag type to disengage optional objects.
80 struct nullopt_t
81 {
82 // Do not user-declare default constructor at all for
83 // optional_value = {} syntax to work.
84 // nullopt_t() = delete;
85
86 // Used for constructing nullopt.
87 enum class _Construct { _Token };
88
89 // Must be constexpr for nullopt_t to be literal.
90 explicit constexpr nullopt_t(_Construct) noexcept { }
91 };
92
93 /// Tag to disengage optional objects.
94 inline constexpr nullopt_t nullopt { nullopt_t::_Construct::_Token };
95
96 template<typename _Fn> struct _Optional_func { _Fn& _M_f; };
97
98 /**
99 * @brief Exception class thrown when a disengaged optional object is
100 * dereferenced.
101 * @ingroup exceptions
102 */
103 class bad_optional_access : public exception
104 {
105 public:
106 bad_optional_access() = default;
107 virtual ~bad_optional_access() = default;
108
109 const char* what() const noexcept override
110 { return "bad optional access"; }
111 };
112
113 // XXX Does not belong here.
114 [[__noreturn__]] inline void
115 __throw_bad_optional_access()
116 { _GLIBCXX_THROW_OR_ABORT(bad_optional_access()); }
117
118 // This class template manages construction/destruction of
119 // the contained value for a std::optional.
120 template <typename _Tp>
121 struct _Optional_payload_base
122 {
123 using _Stored_type = remove_const_t<_Tp>;
124
125 _Optional_payload_base() = default;
126 ~_Optional_payload_base() = default;
127
128 template<typename... _Args>
129 constexpr
130 _Optional_payload_base(in_place_t __tag, _Args&&... __args)
131 : _M_payload(__tag, std::forward<_Args>(__args)...),
132 _M_engaged(true)
133 { }
134
135 template<typename _Up, typename... _Args>
136 constexpr
137 _Optional_payload_base(std::initializer_list<_Up> __il,
138 _Args&&... __args)
139 : _M_payload(__il, std::forward<_Args>(__args)...),
140 _M_engaged(true)
141 { }
142
143 // Constructor used by _Optional_base copy constructor when the
144 // contained value is not trivially copy constructible.
145 constexpr
146 _Optional_payload_base(bool /* __engaged */,
147 const _Optional_payload_base& __other)
148 {
149 if (__other._M_engaged)
150 this->_M_construct(__other._M_get());
151 }
152
153 // Constructor used by _Optional_base move constructor when the
154 // contained value is not trivially move constructible.
155 constexpr
156 _Optional_payload_base(bool /* __engaged */,
157 _Optional_payload_base&& __other)
158 {
159 if (__other._M_engaged)
160 this->_M_construct(std::move(__other._M_get()));
161 }
162
163 // Copy constructor is only used to when the contained value is
164 // trivially copy constructible.
165 _Optional_payload_base(const _Optional_payload_base&) = default;
166
167 // Move constructor is only used to when the contained value is
168 // trivially copy constructible.
169 _Optional_payload_base(_Optional_payload_base&&) = default;
170
171 _Optional_payload_base&
172 operator=(const _Optional_payload_base&) = default;
173
174 _Optional_payload_base&
175 operator=(_Optional_payload_base&&) = default;
176
177 // used to perform non-trivial copy assignment.
178 constexpr void
179 _M_copy_assign(const _Optional_payload_base& __other)
180 {
181 if (this->_M_engaged && __other._M_engaged)
182 this->_M_get() = __other._M_get();
183 else
184 {
185 if (__other._M_engaged)
186 this->_M_construct(__other._M_get());
187 else
188 this->_M_reset();
189 }
190 }
191
192 // used to perform non-trivial move assignment.
193 constexpr void
194 _M_move_assign(_Optional_payload_base&& __other)
195 noexcept(__and_v<is_nothrow_move_constructible<_Tp>,
196 is_nothrow_move_assignable<_Tp>>)
197 {
198 if (this->_M_engaged && __other._M_engaged)
199 this->_M_get() = std::move(__other._M_get());
200 else
201 {
202 if (__other._M_engaged)
203 this->_M_construct(std::move(__other._M_get()));
204 else
205 this->_M_reset();
206 }
207 }
208
209 struct _Empty_byte { };
210
211 template<typename _Up, bool = is_trivially_destructible_v<_Up>>
212 union _Storage
213 {
214 constexpr _Storage() noexcept : _M_empty() { }
215
216 template<typename... _Args>
217 constexpr
218 _Storage(in_place_t, _Args&&... __args)
219 : _M_value(std::forward<_Args>(__args)...)
220 { }
221
222 template<typename _Vp, typename... _Args>
223 constexpr
224 _Storage(std::initializer_list<_Vp> __il, _Args&&... __args)
225 : _M_value(__il, std::forward<_Args>(__args)...)
226 { }
227
228#if __cplusplus >= 202002L
229 template<typename _Fn, typename _Arg>
230 constexpr
231 _Storage(_Optional_func<_Fn> __f, _Arg&& __arg)
232 : _M_value(std::__invoke(std::forward<_Fn>(__f._M_f),
233 std::forward<_Arg>(__arg)))
234 { }
235#endif
236
237#if __cpp_concepts >= 202002L // Conditionally trivial special member functions
238 ~_Storage() = default;
239
240 // User-provided destructor is needed when _Up has non-trivial dtor.
241 _GLIBCXX20_CONSTEXPR
242 ~_Storage() requires (!is_trivially_destructible_v<_Up>)
243 { }
244
245 _Storage(const _Storage&) = default;
246 _Storage(_Storage&&) = default;
247 _Storage& operator=(const _Storage&) = default;
248 _Storage& operator=(_Storage&&) = default;
249#endif
250
251 _Empty_byte _M_empty;
252 _Up _M_value;
253 };
254
255#if __cpp_concepts < 202002L
256 template<typename _Up>
257 union _Storage<_Up, false>
258 {
259 constexpr _Storage() noexcept : _M_empty() { }
260
261 template<typename... _Args>
262 constexpr
263 _Storage(in_place_t, _Args&&... __args)
264 : _M_value(std::forward<_Args>(__args)...)
265 { }
266
267 template<typename _Vp, typename... _Args>
268 constexpr
269 _Storage(std::initializer_list<_Vp> __il, _Args&&... __args)
270 : _M_value(__il, std::forward<_Args>(__args)...)
271 { }
272
273#if __cplusplus >= 202002L
274 template<typename _Fn, typename _Arg>
275 constexpr
276 _Storage(_Optional_func<_Fn> __f, _Arg&& __arg)
277 : _M_value(std::__invoke(std::forward<_Fn>(__f._M_f),
278 std::forward<_Arg>(__arg)))
279 { }
280#endif
281
282 // User-provided destructor is needed when _Up has non-trivial dtor.
283 _GLIBCXX20_CONSTEXPR ~_Storage() { }
284
285 _Storage(const _Storage&) = default;
286 _Storage(_Storage&&) = default;
287 _Storage& operator=(const _Storage&) = default;
288 _Storage& operator=(_Storage&&) = default;
289
290 _Empty_byte _M_empty;
291 _Up _M_value;
292 };
293#endif
294
295 _Storage<_Stored_type> _M_payload;
296
297 bool _M_engaged = false;
298
299 template<typename... _Args>
300 constexpr void
301 _M_construct(_Args&&... __args)
302 noexcept(is_nothrow_constructible_v<_Stored_type, _Args...>)
303 {
304 std::_Construct(std::__addressof(this->_M_payload._M_value),
305 std::forward<_Args>(__args)...);
306 this->_M_engaged = true;
307 }
308
309 constexpr void
310 _M_destroy() noexcept
311 {
312 _M_engaged = false;
313 _M_payload._M_value.~_Stored_type();
314 }
315
316#if __cplusplus >= 202002L
317 template<typename _Fn, typename _Up>
318 constexpr void
319 _M_apply(_Optional_func<_Fn> __f, _Up&& __x)
320 {
321 std::construct_at(std::__addressof(this->_M_payload),
322 __f, std::forward<_Up>(__x));
323 _M_engaged = true;
324 }
325#endif
326
327 // The _M_get() operations have _M_engaged as a precondition.
328 // They exist to access the contained value with the appropriate
329 // const-qualification, because _M_payload has had the const removed.
330
331 constexpr _Tp&
332 _M_get() noexcept
333 { return this->_M_payload._M_value; }
334
335 constexpr const _Tp&
336 _M_get() const noexcept
337 { return this->_M_payload._M_value; }
338
339 // _M_reset is a 'safe' operation with no precondition.
340 constexpr void
341 _M_reset() noexcept
342 {
343 if (this->_M_engaged)
344 _M_destroy();
345 else // This seems redundant but improves codegen, see PR 112480.
346 this->_M_engaged = false;
347 }
348 };
349
350 // Class template that manages the payload for optionals.
351 template <typename _Tp,
352 bool /*_HasTrivialDestructor*/ =
353 is_trivially_destructible_v<_Tp>,
354 bool /*_HasTrivialCopy */ =
355 is_trivially_copy_assignable_v<_Tp>
356 && is_trivially_copy_constructible_v<_Tp>,
357 bool /*_HasTrivialMove */ =
358 is_trivially_move_assignable_v<_Tp>
359 && is_trivially_move_constructible_v<_Tp>>
360 struct _Optional_payload;
361
362 // Payload for potentially-constexpr optionals (trivial copy/move/destroy).
363 template <typename _Tp>
364 struct _Optional_payload<_Tp, true, true, true>
365 : _Optional_payload_base<_Tp>
366 {
367 using _Optional_payload_base<_Tp>::_Optional_payload_base;
368
369 _Optional_payload() = default;
370 };
371
372 // Payload for optionals with non-trivial copy construction/assignment.
373 template <typename _Tp>
374 struct _Optional_payload<_Tp, true, false, true>
375 : _Optional_payload_base<_Tp>
376 {
377 using _Optional_payload_base<_Tp>::_Optional_payload_base;
378
379 _Optional_payload() = default;
380 ~_Optional_payload() = default;
381 _Optional_payload(const _Optional_payload&) = default;
382 _Optional_payload(_Optional_payload&&) = default;
383 _Optional_payload& operator=(_Optional_payload&&) = default;
384
385 // Non-trivial copy assignment.
386 constexpr
387 _Optional_payload&
388 operator=(const _Optional_payload& __other)
389 {
390 this->_M_copy_assign(__other);
391 return *this;
392 }
393 };
394
395 // Payload for optionals with non-trivial move construction/assignment.
396 template <typename _Tp>
397 struct _Optional_payload<_Tp, true, true, false>
398 : _Optional_payload_base<_Tp>
399 {
400 using _Optional_payload_base<_Tp>::_Optional_payload_base;
401
402 _Optional_payload() = default;
403 ~_Optional_payload() = default;
404 _Optional_payload(const _Optional_payload&) = default;
405 _Optional_payload(_Optional_payload&&) = default;
406 _Optional_payload& operator=(const _Optional_payload&) = default;
407
408 // Non-trivial move assignment.
409 constexpr
410 _Optional_payload&
411 operator=(_Optional_payload&& __other)
412 noexcept(__and_v<is_nothrow_move_constructible<_Tp>,
413 is_nothrow_move_assignable<_Tp>>)
414 {
415 this->_M_move_assign(std::move(__other));
416 return *this;
417 }
418 };
419
420 // Payload for optionals with non-trivial copy and move assignment.
421 template <typename _Tp>
422 struct _Optional_payload<_Tp, true, false, false>
423 : _Optional_payload_base<_Tp>
424 {
425 using _Optional_payload_base<_Tp>::_Optional_payload_base;
426
427 _Optional_payload() = default;
428 ~_Optional_payload() = default;
429 _Optional_payload(const _Optional_payload&) = default;
430 _Optional_payload(_Optional_payload&&) = default;
431
432 // Non-trivial copy assignment.
433 constexpr
434 _Optional_payload&
435 operator=(const _Optional_payload& __other)
436 {
437 this->_M_copy_assign(__other);
438 return *this;
439 }
440
441 // Non-trivial move assignment.
442 constexpr
443 _Optional_payload&
444 operator=(_Optional_payload&& __other)
445 noexcept(__and_v<is_nothrow_move_constructible<_Tp>,
446 is_nothrow_move_assignable<_Tp>>)
447 {
448 this->_M_move_assign(std::move(__other));
449 return *this;
450 }
451 };
452
453 // Payload for optionals with non-trivial destructors.
454 template <typename _Tp, bool _Copy, bool _Move>
455 struct _Optional_payload<_Tp, false, _Copy, _Move>
456 : _Optional_payload<_Tp, true, false, false>
457 {
458 // Base class implements all the constructors and assignment operators:
459 using _Optional_payload<_Tp, true, false, false>::_Optional_payload;
460 _Optional_payload() = default;
461 _Optional_payload(const _Optional_payload&) = default;
462 _Optional_payload(_Optional_payload&&) = default;
463 _Optional_payload& operator=(const _Optional_payload&) = default;
464 _Optional_payload& operator=(_Optional_payload&&) = default;
465
466 // Destructor needs to destroy the contained value:
467 _GLIBCXX20_CONSTEXPR ~_Optional_payload() { this->_M_reset(); }
468 };
469
470 /**
471 * @brief Class template that provides copy/move constructors of optional.
472 *
473 * Such a separate base class template is necessary in order to
474 * conditionally make copy/move constructors trivial.
475 *
476 * When the contained value is trivially copy/move constructible,
477 * the copy/move constructors of _Optional_base will invoke the
478 * trivial copy/move constructor of _Optional_payload. Otherwise,
479 * they will invoke _Optional_payload(bool, const _Optional_payload&)
480 * or _Optional_payload(bool, _Optional_payload&&) to initialize
481 * the contained value, if copying/moving an engaged optional.
482 *
483 * Whether the other special members are trivial is determined by the
484 * _Optional_payload<_Tp> specialization used for the _M_payload member.
485 *
486 * @see optional, _Enable_special_members
487 */
488 template<typename _Tp,
489 bool = is_trivially_copy_constructible_v<_Tp>,
490 bool = is_trivially_move_constructible_v<_Tp>>
491 struct _Optional_base
492 {
493 // Constructors for disengaged optionals.
494 constexpr _Optional_base() = default;
495
496 // Constructors for engaged optionals.
497 template<typename... _Args,
498 enable_if_t<is_constructible_v<_Tp, _Args...>, bool> = false>
499 constexpr explicit
500 _Optional_base(in_place_t, _Args&&... __args)
501 : _M_payload(in_place, std::forward<_Args>(__args)...)
502 { }
503
504 template<typename _Up, typename... _Args,
505 enable_if_t<is_constructible_v<_Tp,
506 initializer_list<_Up>&,
507 _Args...>, bool> = false>
508 constexpr explicit
509 _Optional_base(in_place_t,
510 initializer_list<_Up> __il,
511 _Args&&... __args)
512 : _M_payload(in_place, __il, std::forward<_Args>(__args)...)
513 { }
514
515 // Copy and move constructors.
516 constexpr
517 _Optional_base(const _Optional_base& __other)
518 noexcept(is_nothrow_copy_constructible_v<_Tp>)
519 : _M_payload(__other._M_payload._M_engaged, __other._M_payload)
520 { }
521
522 constexpr
523 _Optional_base(_Optional_base&& __other)
524 noexcept(is_nothrow_move_constructible_v<_Tp>)
525 : _M_payload(__other._M_payload._M_engaged,
526 std::move(__other._M_payload))
527 { }
528
529#if __cpp_concepts >= 202002L // Conditionally trivial special member functions
530 // Define these in the primary template if possible, so that we don't
531 // need to use partial specializations of this class template.
532 constexpr _Optional_base(const _Optional_base&)
533 requires is_trivially_copy_constructible_v<_Tp> = default;
534
535 constexpr _Optional_base(_Optional_base&&)
536 requires is_trivially_move_constructible_v<_Tp> = default;
537#endif
538
539 // Assignment operators.
540 _Optional_base& operator=(const _Optional_base&) = default;
541 _Optional_base& operator=(_Optional_base&&) = default;
542
543 _Optional_payload<_Tp> _M_payload;
544
545 protected:
546 // For the primary template, we define these functions here.
547 using _Stored_type = remove_const_t<_Tp>;
548
549 // The _M_construct operation has !_M_engaged as a precondition
550 // while _M_destruct has _M_engaged as a precondition.
551 template<typename... _Args>
552 constexpr void
553 _M_construct(_Args&&... __args)
554 noexcept(is_nothrow_constructible_v<_Stored_type, _Args...>)
555 {
556 _M_payload._M_construct(std::forward<_Args>(__args)...);
557 }
558
559 constexpr void
560 _M_destruct() noexcept
561 { _M_payload._M_destroy(); }
562
563 // _M_reset is a 'safe' operation with no precondition.
564 constexpr void
565 _M_reset() noexcept
566 { _M_payload._M_reset(); }
567
568 constexpr bool _M_is_engaged() const noexcept
569 { return _M_payload._M_engaged; }
570
571 // The _M_get operations have _M_engaged as a precondition.
572 constexpr _Tp&
573 _M_get() noexcept
574 { return _M_payload._M_get(); }
575
576 constexpr const _Tp&
577 _M_get() const noexcept
578 { return _M_payload._M_get(); }
579 };
580
581#if __cpp_concepts < 202002L
582 // If P0848R3 "Conditionally Trivial Special Member Functions" is not
583 // supported (as determined from the __cpp_concepts macro value), the
584 // _Optional_base primary template only has non-trivial copy and move
585 // constructors. Use partial specializations of _Optional_base<T, C, M>
586 // that have a trivial copy and/or move constructor.
587
588 // Common base class for _Optional_base<T> to avoid repeating these
589 // member functions in each partial specialization.
590 // Only used if P0848R3 "Conditionally Trivial Special Member Functions"
591 // is not supported, as indicated by the __cpp_concepts value.
592 template<typename _Tp, typename _Dp>
593 class _Optional_base_impl
594 {
595 protected:
596 using _Stored_type = remove_const_t<_Tp>;
597
598 // The _M_construct operation has !_M_engaged as a precondition
599 // while _M_destruct has _M_engaged as a precondition.
600 template<typename... _Args>
601 constexpr void
602 _M_construct(_Args&&... __args)
603 noexcept(is_nothrow_constructible_v<_Stored_type, _Args...>)
604 {
605 static_cast<_Dp*>(this)->_M_payload._M_construct(
606 std::forward<_Args>(__args)...);
607 }
608
609 constexpr void
610 _M_destruct() noexcept
611 { static_cast<_Dp*>(this)->_M_payload._M_destroy(); }
612
613 // _M_reset is a 'safe' operation with no precondition.
614 constexpr void
615 _M_reset() noexcept
616 { static_cast<_Dp*>(this)->_M_payload._M_reset(); }
617
618 constexpr bool _M_is_engaged() const noexcept
619 { return static_cast<const _Dp*>(this)->_M_payload._M_engaged; }
620
621 // The _M_get operations have _M_engaged as a precondition.
622 constexpr _Tp&
623 _M_get() noexcept
624 { return static_cast<_Dp*>(this)->_M_payload._M_get(); }
625
626 constexpr const _Tp&
627 _M_get() const noexcept
628 { return static_cast<const _Dp*>(this)->_M_payload._M_get(); }
629 };
630
631 template<typename _Tp>
632 struct _Optional_base<_Tp, false, true> // trivial move ctor
633 : _Optional_base_impl<_Tp, _Optional_base<_Tp>>
634 {
635 // Constructors for disengaged optionals.
636 constexpr _Optional_base() = default;
637
638 // Constructors for engaged optionals.
639 template<typename... _Args,
640 enable_if_t<is_constructible_v<_Tp, _Args...>, bool> = false>
641 constexpr explicit
642 _Optional_base(in_place_t, _Args&&... __args)
643 : _M_payload(in_place, std::forward<_Args>(__args)...)
644 { }
645
646 template<typename _Up, typename... _Args,
647 enable_if_t<is_constructible_v<_Tp,
648 initializer_list<_Up>&,
649 _Args...>, bool> = false>
650 constexpr explicit
651 _Optional_base(in_place_t,
652 initializer_list<_Up> __il,
653 _Args... __args)
654 : _M_payload(in_place, __il, std::forward<_Args>(__args)...)
655 { }
656
657 // Copy and move constructors.
658 constexpr _Optional_base(const _Optional_base& __other)
659 : _M_payload(__other._M_payload._M_engaged, __other._M_payload)
660 { }
661
662 constexpr _Optional_base(_Optional_base&& __other) = default;
663
664 // Assignment operators.
665 _Optional_base& operator=(const _Optional_base&) = default;
666 _Optional_base& operator=(_Optional_base&&) = default;
667
668 _Optional_payload<_Tp> _M_payload;
669 };
670
671 template<typename _Tp>
672 struct _Optional_base<_Tp, true, false> // trivial copy ctor
673 : _Optional_base_impl<_Tp, _Optional_base<_Tp>>
674 {
675 // Constructors for disengaged optionals.
676 constexpr _Optional_base() = default;
677
678 // Constructors for engaged optionals.
679 template<typename... _Args,
680 enable_if_t<is_constructible_v<_Tp, _Args...>, bool> = false>
681 constexpr explicit
682 _Optional_base(in_place_t, _Args&&... __args)
683 : _M_payload(in_place, std::forward<_Args>(__args)...)
684 { }
685
686 template<typename _Up, typename... _Args,
687 enable_if_t<is_constructible_v<_Tp,
688 initializer_list<_Up>&,
689 _Args...>, bool> = false>
690 constexpr explicit
691 _Optional_base(in_place_t,
692 initializer_list<_Up> __il,
693 _Args&&... __args)
694 : _M_payload(in_place, __il, std::forward<_Args>(__args)...)
695 { }
696
697 // Copy and move constructors.
698 constexpr _Optional_base(const _Optional_base& __other) = default;
699
700 constexpr
701 _Optional_base(_Optional_base&& __other)
702 noexcept(is_nothrow_move_constructible_v<_Tp>)
703 : _M_payload(__other._M_payload._M_engaged,
704 std::move(__other._M_payload))
705 { }
706
707 // Assignment operators.
708 _Optional_base& operator=(const _Optional_base&) = default;
709 _Optional_base& operator=(_Optional_base&&) = default;
710
711 _Optional_payload<_Tp> _M_payload;
712 };
713
714 template<typename _Tp>
715 struct _Optional_base<_Tp, true, true> // trivial copy and move ctors
716 : _Optional_base_impl<_Tp, _Optional_base<_Tp>>
717 {
718 // Constructors for disengaged optionals.
719 constexpr _Optional_base() = default;
720
721 // Constructors for engaged optionals.
722 template<typename... _Args,
723 enable_if_t<is_constructible_v<_Tp, _Args...>, bool> = false>
724 constexpr explicit
725 _Optional_base(in_place_t, _Args&&... __args)
726 : _M_payload(in_place, std::forward<_Args>(__args)...)
727 { }
728
729 template<typename _Up, typename... _Args,
730 enable_if_t<is_constructible_v<_Tp,
731 initializer_list<_Up>&,
732 _Args...>, bool> = false>
733 constexpr explicit
734 _Optional_base(in_place_t,
735 initializer_list<_Up> __il,
736 _Args&&... __args)
737 : _M_payload(in_place, __il, std::forward<_Args>(__args)...)
738 { }
739
740 // Copy and move constructors.
741 constexpr _Optional_base(const _Optional_base& __other) = default;
742 constexpr _Optional_base(_Optional_base&& __other) = default;
743
744 // Assignment operators.
745 _Optional_base& operator=(const _Optional_base&) = default;
746 _Optional_base& operator=(_Optional_base&&) = default;
747
748 _Optional_payload<_Tp> _M_payload;
749 };
750#endif // __cpp_concepts
751
752 template<typename _Tp>
753 inline constexpr bool __is_optional_v = false;
754 template<typename _Tp>
755 inline constexpr bool __is_optional_v<optional<_Tp>> = true;
756
757 template<typename _Tp, typename _Wp>
758 using __converts_from_any_cvref = __or_<
759 is_constructible<_Tp, _Wp&>, is_convertible<_Wp&, _Tp>,
760 is_constructible<_Tp, _Wp>, is_convertible<_Wp, _Tp>,
761 is_constructible<_Tp, const _Wp&>, is_convertible<const _Wp&, _Tp>,
762 is_constructible<_Tp, const _Wp>, is_convertible<const _Wp, _Tp>
763 >;
764
765 template<typename _Tp, typename _Up>
766 using __converts_from_optional
767 = __converts_from_any_cvref<_Tp, optional<_Up>>;
768
769 template<typename _Tp, typename _Up>
770 using __assigns_from_optional =
771 __or_<is_assignable<_Tp&, const optional<_Up>&>,
772 is_assignable<_Tp&, optional<_Up>&>,
773 is_assignable<_Tp&, const optional<_Up>&&>,
774 is_assignable<_Tp&, optional<_Up>&&>>;
775
776#if __cpp_concepts && __cpp_conditional_explicit && __glibcxx_remove_cvref
777# define _GLIBCXX_USE_CONSTRAINTS_FOR_OPTIONAL 1
778#endif
779
780 template<typename _Tp>
781 inline constexpr bool __is_valid_contained_type_for_optional =
782 (
783#if __cpp_lib_optional >= 202506L
784 is_lvalue_reference_v<_Tp> ||
785#endif
786 (is_object_v<_Tp> && is_destructible_v<_Tp> && !is_array_v<_Tp>)
787 )
788 && !is_same_v<remove_cv_t<remove_reference_t<_Tp>>, nullopt_t>
789 && !is_same_v<remove_cv_t<remove_reference_t<_Tp>>, in_place_t>;
790
791 /**
792 * @brief Class template for optional values.
793 */
794 template<typename _Tp>
795 class optional
796 : private _Optional_base<_Tp>,
797 private _Enable_copy_move<
798 // Copy constructor.
799 is_copy_constructible_v<_Tp>,
800 // Copy assignment.
801 __and_v<is_copy_constructible<_Tp>, is_copy_assignable<_Tp>>,
802 // Move constructor.
803 is_move_constructible_v<_Tp>,
804 // Move assignment.
805 __and_v<is_move_constructible<_Tp>, is_move_assignable<_Tp>>,
806 // Unique tag type.
807 optional<_Tp>>
808 {
809 static_assert(__is_valid_contained_type_for_optional<_Tp>);
810
811 private:
812 using _Base = _Optional_base<_Tp>;
813
814 // SFINAE helpers
815
816 // _GLIBCXX_RESOLVE_LIB_DEFECTS
817 // 3836. std::expected<bool, E1> conversion constructor
818 // expected(const expected<U, G>&) should take precedence over
819 // expected(U&&) with operator bool
820#ifdef _GLIBCXX_USE_CONSTRAINTS_FOR_OPTIONAL
821 template<typename _From, typename = remove_cv_t<_Tp>>
822 static constexpr bool __not_constructing_bool_from_optional
823 = true;
824
825 // If T is cv bool, remove_cvref_t<U> is not a specialization of optional
826 // i.e. do not initialize a bool from optional<U>::operator bool().
827 template<typename _From>
828 static constexpr bool
829 __not_constructing_bool_from_optional<_From, bool>
830 = !__is_optional_v<remove_cvref_t<_From>>;
831
832 // If T is not cv bool, converts-from-any-cvref<T, optional<U>> is false.
833 // The constructor that converts from optional<U> is disabled if the
834 // contained value can be initialized from optional<U>, so that the
835 // optional(U&&) constructor can be used instead.
836 template<typename _From, typename = remove_cv_t<_Tp>>
837 static constexpr bool __construct_from_contained_value
838 = !__converts_from_optional<_Tp, _From>::value;
839
840 // However, optional<U> can always be converted to bool, so don't apply
841 // this constraint when T is cv bool.
842 template<typename _From>
843 static constexpr bool __construct_from_contained_value<_From, bool>
844 = true;
845#else
846 template<typename _From, typename = remove_cv_t<_Tp>>
847 struct __not_constructing_bool_from_optional
848 : true_type
849 { };
850
851 template<typename _From>
852 struct __not_constructing_bool_from_optional<_From, bool>
853 : bool_constant<!__is_optional_v<__remove_cvref_t<_From>>>
854 { };
855
856 template<typename _From, typename = remove_cv_t<_Tp>>
857 struct __construct_from_contained_value
858 : __not_<__converts_from_optional<_Tp, _From>>
859 { };
860
861 template<typename _From>
862 struct __construct_from_contained_value<_From, bool>
863 : true_type
864 { };
865
866 template<typename _Up>
867 using __not_self = __not_<is_same<optional, __remove_cvref_t<_Up>>>;
868 template<typename _Up>
869 using __not_tag = __not_<is_same<in_place_t, __remove_cvref_t<_Up>>>;
870 template<typename... _Cond>
871 using _Requires = enable_if_t<__and_v<_Cond...>, bool>;
872#endif
873
874 public:
875 using value_type = _Tp;
876#ifdef __cpp_lib_optional_range_support // >= C++26
877 using iterator = __gnu_cxx::__normal_iterator<_Tp*, optional>;
878 using const_iterator = __gnu_cxx::__normal_iterator<const _Tp*, optional>;
879#endif
880
881 constexpr optional() noexcept { }
882
883 constexpr optional(nullopt_t) noexcept { }
884
885 // Converting constructors for engaged optionals.
886#ifdef _GLIBCXX_USE_CONSTRAINTS_FOR_OPTIONAL
887 template<typename _Up = remove_cv_t<_Tp>>
888 requires (!is_same_v<optional, remove_cvref_t<_Up>>)
889 && (!is_same_v<in_place_t, remove_cvref_t<_Up>>)
890 && is_constructible_v<_Tp, _Up>
891 && __not_constructing_bool_from_optional<_Up>
892 constexpr explicit(!is_convertible_v<_Up, _Tp>)
893 optional(_Up&& __t)
894 noexcept(is_nothrow_constructible_v<_Tp, _Up>)
895 : _Base(std::in_place, std::forward<_Up>(__t)) { }
896
897 template<typename _Up>
898 requires (!is_same_v<_Tp, _Up>)
899 && is_constructible_v<_Tp, const _Up&>
900 && __construct_from_contained_value<_Up>
901 constexpr explicit(!is_convertible_v<const _Up&, _Tp>)
902 optional(const optional<_Up>& __t)
903 noexcept(is_nothrow_constructible_v<_Tp, const _Up&>)
904 {
905 if (__t)
906 emplace(__t._M_fwd());
907 }
908
909 template<typename _Up>
910 requires (!is_same_v<_Tp, _Up>)
911 && is_constructible_v<_Tp, _Up>
912 && __construct_from_contained_value<_Up>
913 constexpr explicit(!is_convertible_v<_Up, _Tp>)
914 optional(optional<_Up>&& __t)
915 noexcept(is_nothrow_constructible_v<_Tp, _Up>)
916 {
917 if (__t)
918 emplace(std::move(__t)._M_fwd());
919 }
920
921 template<typename... _Args>
922 requires is_constructible_v<_Tp, _Args...>
923 explicit constexpr
924 optional(in_place_t, _Args&&... __args)
925 noexcept(is_nothrow_constructible_v<_Tp, _Args...>)
926 : _Base(std::in_place, std::forward<_Args>(__args)...)
927 { }
928
929 template<typename _Up, typename... _Args>
930 requires is_constructible_v<_Tp, initializer_list<_Up>&, _Args...>
931 explicit constexpr
932 optional(in_place_t, initializer_list<_Up> __il, _Args&&... __args)
933 noexcept(is_nothrow_constructible_v<_Tp, initializer_list<_Up>&,
934 _Args...>)
935 : _Base(std::in_place, __il, std::forward<_Args>(__args)...)
936 { }
937#else
938 template<typename _Up = remove_cv_t<_Tp>,
939 _Requires<__not_self<_Up>, __not_tag<_Up>,
940 is_constructible<_Tp, _Up>,
941 is_convertible<_Up, _Tp>,
942 __not_constructing_bool_from_optional<_Up>> = true>
943 constexpr
944 optional(_Up&& __t)
945 noexcept(is_nothrow_constructible_v<_Tp, _Up>)
946 : _Base(std::in_place, std::forward<_Up>(__t)) { }
947
948 template<typename _Up = remove_cv_t<_Tp>,
949 _Requires<__not_self<_Up>, __not_tag<_Up>,
950 is_constructible<_Tp, _Up>,
951 __not_<is_convertible<_Up, _Tp>>,
952 __not_constructing_bool_from_optional<_Up>> = false>
953 explicit constexpr
954 optional(_Up&& __t)
955 noexcept(is_nothrow_constructible_v<_Tp, _Up>)
956 : _Base(std::in_place, std::forward<_Up>(__t)) { }
957
958 template<typename _Up,
959 _Requires<__not_<is_same<_Tp, _Up>>,
960 is_constructible<_Tp, const _Up&>,
961 is_convertible<const _Up&, _Tp>,
962 __construct_from_contained_value<_Up>> = true>
963 constexpr
964 optional(const optional<_Up>& __t)
965 noexcept(is_nothrow_constructible_v<_Tp, const _Up&>)
966 {
967 if (__t)
968 emplace(__t._M_fwd());
969 }
970
971 template<typename _Up,
972 _Requires<__not_<is_same<_Tp, _Up>>,
973 is_constructible<_Tp, const _Up&>,
974 __not_<is_convertible<const _Up&, _Tp>>,
975 __construct_from_contained_value<_Up>> = false>
976 explicit constexpr
977 optional(const optional<_Up>& __t)
978 noexcept(is_nothrow_constructible_v<_Tp, const _Up&>)
979 {
980 if (__t)
981 emplace(__t._M_fwd());
982 }
983
984 template<typename _Up,
985 _Requires<__not_<is_same<_Tp, _Up>>,
986 is_constructible<_Tp, _Up>,
987 is_convertible<_Up, _Tp>,
988 __construct_from_contained_value<_Up>> = true>
989 constexpr
990 optional(optional<_Up>&& __t)
991 noexcept(is_nothrow_constructible_v<_Tp, _Up>)
992 {
993 if (__t)
994 emplace(std::move(__t)._M_fwd());
995 }
996
997 template<typename _Up,
998 _Requires<__not_<is_same<_Tp, _Up>>,
999 is_constructible<_Tp, _Up>,
1000 __not_<is_convertible<_Up, _Tp>>,
1001 __construct_from_contained_value<_Up>> = false>
1002 explicit constexpr
1003 optional(optional<_Up>&& __t)
1004 noexcept(is_nothrow_constructible_v<_Tp, _Up>)
1005 {
1006 if (__t)
1007 emplace(std::move(__t)._M_fwd());
1008 }
1009
1010 template<typename... _Args,
1011 _Requires<is_constructible<_Tp, _Args...>> = false>
1012 explicit constexpr
1013 optional(in_place_t, _Args&&... __args)
1014 noexcept(is_nothrow_constructible_v<_Tp, _Args...>)
1015 : _Base(std::in_place, std::forward<_Args>(__args)...) { }
1016
1017 template<typename _Up, typename... _Args,
1018 _Requires<is_constructible<_Tp,
1019 initializer_list<_Up>&,
1020 _Args...>> = false>
1021 explicit constexpr
1022 optional(in_place_t, initializer_list<_Up> __il, _Args&&... __args)
1023 noexcept(is_nothrow_constructible_v<_Tp, initializer_list<_Up>&,
1024 _Args...>)
1025 : _Base(std::in_place, __il, std::forward<_Args>(__args)...) { }
1026#endif
1027
1028 // Assignment operators.
1029 _GLIBCXX20_CONSTEXPR optional&
1030 operator=(nullopt_t) noexcept
1031 {
1032 this->_M_reset();
1033 return *this;
1034 }
1035
1036 template<typename _Up = remove_cv_t<_Tp>>
1037#ifdef _GLIBCXX_USE_CONSTRAINTS_FOR_OPTIONAL
1038 requires (!is_same_v<optional, remove_cvref_t<_Up>>)
1039 && (!(is_scalar_v<_Tp> && is_same_v<_Tp, decay_t<_Up>>))
1040 && is_constructible_v<_Tp, _Up>
1041 && is_assignable_v<_Tp&, _Up>
1042 constexpr optional&
1043#else
1044 enable_if_t<__and_v<__not_self<_Up>,
1045 __not_<__and_<is_scalar<_Tp>,
1046 is_same<_Tp, decay_t<_Up>>>>,
1047 is_constructible<_Tp, _Up>,
1048 is_assignable<_Tp&, _Up>>,
1049 optional&>
1050#endif
1051 operator=(_Up&& __u)
1052 noexcept(__and_v<is_nothrow_constructible<_Tp, _Up>,
1053 is_nothrow_assignable<_Tp&, _Up>>)
1054 {
1055 if (this->_M_is_engaged())
1056 this->_M_get() = std::forward<_Up>(__u);
1057 else
1058 this->_M_construct(std::forward<_Up>(__u));
1059
1060 return *this;
1061 }
1062
1063 template<typename _Up>
1064#ifdef _GLIBCXX_USE_CONSTRAINTS_FOR_OPTIONAL
1065 requires (!is_same_v<_Tp, _Up>)
1066 && is_constructible_v<_Tp, const _Up&>
1067 && is_assignable_v<_Tp&, const _Up&>
1068 && (!__converts_from_optional<_Tp, _Up>::value)
1069 && (!__assigns_from_optional<_Tp, _Up>::value)
1070 constexpr optional&
1071#else
1072 enable_if_t<__and_v<__not_<is_same<_Tp, _Up>>,
1073 is_constructible<_Tp, const _Up&>,
1074 is_assignable<_Tp&, const _Up&>,
1075 __not_<__converts_from_optional<_Tp, _Up>>,
1076 __not_<__assigns_from_optional<_Tp, _Up>>>,
1077 optional&>
1078#endif
1079 operator=(const optional<_Up>& __u)
1080 noexcept(__and_v<is_nothrow_constructible<_Tp, const _Up&>,
1081 is_nothrow_assignable<_Tp&, const _Up&>>)
1082 {
1083 if (__u)
1084 {
1085 if (this->_M_is_engaged())
1086 this->_M_get() = __u._M_fwd();
1087 else
1088 this->_M_construct(__u._M_fwd());
1089 }
1090 else
1091 {
1092 this->_M_reset();
1093 }
1094 return *this;
1095 }
1096
1097 template<typename _Up>
1098#ifdef _GLIBCXX_USE_CONSTRAINTS_FOR_OPTIONAL
1099 requires (!is_same_v<_Tp, _Up>)
1100 && is_constructible_v<_Tp, _Up>
1101 && is_assignable_v<_Tp&, _Up>
1102 && (!__converts_from_optional<_Tp, _Up>::value)
1103 && (!__assigns_from_optional<_Tp, _Up>::value)
1104 constexpr optional&
1105#else
1106 enable_if_t<__and_v<__not_<is_same<_Tp, _Up>>,
1107 is_constructible<_Tp, _Up>,
1108 is_assignable<_Tp&, _Up>,
1109 __not_<__converts_from_optional<_Tp, _Up>>,
1110 __not_<__assigns_from_optional<_Tp, _Up>>>,
1111 optional&>
1112#endif
1113 operator=(optional<_Up>&& __u)
1114 noexcept(__and_v<is_nothrow_constructible<_Tp, _Up>,
1115 is_nothrow_assignable<_Tp&, _Up>>)
1116 {
1117 if (__u)
1118 {
1119 if (this->_M_is_engaged())
1120 this->_M_get() = std::move(__u)._M_fwd();
1121 else
1122 this->_M_construct(std::move(__u)._M_fwd());
1123 }
1124 else
1125 {
1126 this->_M_reset();
1127 }
1128
1129 return *this;
1130 }
1131
1132 template<typename... _Args>
1133 _GLIBCXX20_CONSTEXPR
1134 enable_if_t<is_constructible_v<_Tp, _Args...>, _Tp&>
1135 emplace(_Args&&... __args)
1136 noexcept(is_nothrow_constructible_v<_Tp, _Args...>)
1137 {
1138 this->_M_reset();
1139 this->_M_construct(std::forward<_Args>(__args)...);
1140 return this->_M_get();
1141 }
1142
1143 template<typename _Up, typename... _Args>
1144 _GLIBCXX20_CONSTEXPR
1145 enable_if_t<is_constructible_v<_Tp, initializer_list<_Up>&, _Args...>,
1146 _Tp&>
1147 emplace(initializer_list<_Up> __il, _Args&&... __args)
1148 noexcept(is_nothrow_constructible_v<_Tp, initializer_list<_Up>&,
1149 _Args...>)
1150 {
1151 this->_M_reset();
1152 this->_M_construct(__il, std::forward<_Args>(__args)...);
1153 return this->_M_get();
1154 }
1155
1156 // Destructor is implicit, implemented in _Optional_base.
1157
1158 // Swap.
1159 _GLIBCXX20_CONSTEXPR void
1160 swap(optional& __other)
1161 noexcept(is_nothrow_move_constructible_v<_Tp>
1162 && is_nothrow_swappable_v<_Tp>)
1163 {
1164 using std::swap;
1165
1166 if (this->_M_is_engaged() && __other._M_is_engaged())
1167 swap(this->_M_get(), __other._M_get());
1168 else if (this->_M_is_engaged())
1169 {
1170 __other._M_construct(std::move(this->_M_get()));
1171 this->_M_destruct();
1172 }
1173 else if (__other._M_is_engaged())
1174 {
1175 this->_M_construct(std::move(__other._M_get()));
1176 __other._M_destruct();
1177 }
1178 }
1179
1180#ifdef __cpp_lib_optional_range_support // >= C++26
1181 // Iterator support.
1182 constexpr iterator begin() noexcept
1183 {
1184 return iterator(
1185 this->_M_is_engaged() ? std::addressof(this->_M_get()) : nullptr
1186 );
1187 }
1188
1189 constexpr const_iterator begin() const noexcept
1190 {
1191 return const_iterator(
1192 this->_M_is_engaged() ? std::addressof(this->_M_get()) : nullptr
1193 );
1194 }
1195
1196 constexpr iterator end() noexcept
1197 {
1198 return begin() + has_value();
1199 }
1200
1201 constexpr const_iterator end() const noexcept
1202 {
1203 return begin() + has_value();
1204 }
1205#endif // __cpp_lib_optional_range_support
1206
1207 // Observers.
1208 constexpr const _Tp*
1209 operator->() const noexcept
1210 {
1211 __glibcxx_assert(this->_M_is_engaged());
1212 return std::__addressof(this->_M_get());
1213 }
1214
1215 constexpr _Tp*
1216 operator->() noexcept
1217 {
1218 __glibcxx_assert(this->_M_is_engaged());
1219 return std::__addressof(this->_M_get());
1220 }
1221
1222 constexpr const _Tp&
1223 operator*() const& noexcept
1224 {
1225 __glibcxx_assert(this->_M_is_engaged());
1226 return this->_M_get();
1227 }
1228
1229 constexpr _Tp&
1230 operator*()& noexcept
1231 {
1232 __glibcxx_assert(this->_M_is_engaged());
1233 return this->_M_get();
1234 }
1235
1236 constexpr _Tp&&
1237 operator*()&& noexcept
1238 {
1239 __glibcxx_assert(this->_M_is_engaged());
1240 return std::move(this->_M_get());
1241 }
1242
1243 constexpr const _Tp&&
1244 operator*() const&& noexcept
1245 {
1246 __glibcxx_assert(this->_M_is_engaged());
1247 return std::move(this->_M_get());
1248 }
1249
1250 constexpr explicit operator bool() const noexcept
1251 { return this->_M_is_engaged(); }
1252
1253 constexpr bool has_value() const noexcept
1254 { return this->_M_is_engaged(); }
1255
1256 constexpr const _Tp&
1257 value() const&
1258 {
1259 if (this->_M_is_engaged())
1260 return this->_M_get();
1261 __throw_bad_optional_access();
1262 }
1263
1264 constexpr _Tp&
1265 value()&
1266 {
1267 if (this->_M_is_engaged())
1268 return this->_M_get();
1269 __throw_bad_optional_access();
1270 }
1271
1272 constexpr _Tp&&
1273 value()&&
1274 {
1275 if (this->_M_is_engaged())
1276 return std::move(this->_M_get());
1277 __throw_bad_optional_access();
1278 }
1279
1280 constexpr const _Tp&&
1281 value() const&&
1282 {
1283 if (this->_M_is_engaged())
1284 return std::move(this->_M_get());
1285 __throw_bad_optional_access();
1286 }
1287
1288 template<typename _Up = remove_cv_t<_Tp>>
1289 constexpr _Tp
1290 value_or(_Up&& __u) const&
1291 {
1292 static_assert(is_copy_constructible_v<_Tp>);
1293 static_assert(is_convertible_v<_Up&&, _Tp>);
1294
1295 if (this->_M_is_engaged())
1296 return this->_M_get();
1297 else
1298 return static_cast<_Tp>(std::forward<_Up>(__u));
1299 }
1300
1301 template<typename _Up = remove_cv_t<_Tp>>
1302 constexpr _Tp
1303 value_or(_Up&& __u) &&
1304 {
1305 static_assert(is_move_constructible_v<_Tp>);
1306 static_assert(is_convertible_v<_Up&&, _Tp>);
1307
1308 if (this->_M_is_engaged())
1309 return std::move(this->_M_get());
1310 else
1311 return static_cast<_Tp>(std::forward<_Up>(__u));
1312 }
1313
1314#if __cpp_lib_optional >= 202110L // C++23
1315 // [optional.monadic]
1316
1317 template<typename _Fn>
1318 constexpr auto
1319 and_then(_Fn&& __f) &
1320 {
1321 using _Up = remove_cvref_t<invoke_result_t<_Fn, _Tp&>>;
1322 static_assert(__is_optional_v<_Up>,
1323 "the function passed to std::optional<T>::and_then "
1324 "must return a std::optional");
1325 if (has_value())
1326 return std::__invoke(std::forward<_Fn>(__f), _M_get());
1327 else
1328 return _Up();
1329 }
1330
1331 template<typename _Fn>
1332 constexpr auto
1333 and_then(_Fn&& __f) const &
1334 {
1335 using _Up = remove_cvref_t<invoke_result_t<_Fn, const _Tp&>>;
1336 static_assert(__is_optional_v<_Up>,
1337 "the function passed to std::optional<T>::and_then "
1338 "must return a std::optional");
1339 if (has_value())
1340 return std::__invoke(std::forward<_Fn>(__f), _M_get());
1341 else
1342 return _Up();
1343 }
1344
1345 template<typename _Fn>
1346 constexpr auto
1347 and_then(_Fn&& __f) &&
1348 {
1349 using _Up = remove_cvref_t<invoke_result_t<_Fn, _Tp>>;
1350 static_assert(__is_optional_v<_Up>,
1351 "the function passed to std::optional<T>::and_then "
1352 "must return a std::optional");
1353 if (has_value())
1354 return std::__invoke(std::forward<_Fn>(__f), std::move(_M_get()));
1355 else
1356 return _Up();
1357 }
1358
1359 template<typename _Fn>
1360 constexpr auto
1361 and_then(_Fn&& __f) const &&
1362 {
1363 using _Up = remove_cvref_t<invoke_result_t<_Fn, const _Tp>>;
1364 static_assert(__is_optional_v<_Up>,
1365 "the function passed to std::optional<T>::and_then "
1366 "must return a std::optional");
1367 if (has_value())
1368 return std::__invoke(std::forward<_Fn>(__f), std::move(_M_get()));
1369 else
1370 return _Up();
1371 }
1372
1373 template<typename _Fn>
1374 constexpr auto
1375 transform(_Fn&& __f) &
1376 {
1377 using _Up = remove_cv_t<invoke_result_t<_Fn, _Tp&>>;
1378 if (has_value())
1379 return optional<_Up>(_Optional_func<_Fn>{__f}, _M_get());
1380 else
1381 return optional<_Up>();
1382 }
1383
1384 template<typename _Fn>
1385 constexpr auto
1386 transform(_Fn&& __f) const &
1387 {
1388 using _Up = remove_cv_t<invoke_result_t<_Fn, const _Tp&>>;
1389 if (has_value())
1390 return optional<_Up>(_Optional_func<_Fn>{__f}, _M_get());
1391 else
1392 return optional<_Up>();
1393 }
1394
1395 template<typename _Fn>
1396 constexpr auto
1397 transform(_Fn&& __f) &&
1398 {
1399 using _Up = remove_cv_t<invoke_result_t<_Fn, _Tp>>;
1400 if (has_value())
1401 return optional<_Up>(_Optional_func<_Fn>{__f}, std::move(_M_get()));
1402 else
1403 return optional<_Up>();
1404 }
1405
1406 template<typename _Fn>
1407 constexpr auto
1408 transform(_Fn&& __f) const &&
1409 {
1410 using _Up = remove_cv_t<invoke_result_t<_Fn, const _Tp>>;
1411 if (has_value())
1412 return optional<_Up>(_Optional_func<_Fn>{__f}, std::move(_M_get()));
1413 else
1414 return optional<_Up>();
1415 }
1416
1417 template<typename _Fn> requires invocable<_Fn> && copy_constructible<_Tp>
1418 constexpr optional
1419 or_else(_Fn&& __f) const&
1420 {
1421 using _Up = invoke_result_t<_Fn>;
1422 static_assert(is_same_v<remove_cvref_t<_Up>, optional>,
1423 "the function passed to std::optional<T>::or_else "
1424 "must return a std::optional<T>");
1425
1426 if (has_value())
1427 return *this;
1428 else
1429 return std::forward<_Fn>(__f)();
1430 }
1431
1432 template<typename _Fn> requires invocable<_Fn> && move_constructible<_Tp>
1433 constexpr optional
1434 or_else(_Fn&& __f) &&
1435 {
1436 using _Up = invoke_result_t<_Fn>;
1437 static_assert(is_same_v<remove_cvref_t<_Up>, optional>,
1438 "the function passed to std::optional<T>::or_else "
1439 "must return a std::optional<T>");
1440
1441 if (has_value())
1442 return std::move(*this);
1443 else
1444 return std::forward<_Fn>(__f)();
1445 }
1446#endif
1447
1448 _GLIBCXX20_CONSTEXPR void reset() noexcept { this->_M_reset(); }
1449
1450 private:
1451 using _Base::_M_get;
1452
1453 [[__gnu__::__always_inline__]]
1454 constexpr _Tp&
1455 _M_fwd() & noexcept
1456 { return _M_get(); }
1457
1458 [[__gnu__::__always_inline__]]
1459 constexpr _Tp&&
1460 _M_fwd() && noexcept
1461 { return std::move(_M_get()); }
1462
1463 [[__gnu__::__always_inline__]]
1464 constexpr const _Tp&
1465 _M_fwd() const& noexcept
1466 { return _M_get(); }
1467
1468 [[__gnu__::__always_inline__]]
1469 constexpr const _Tp&&
1470 _M_fwd() const&& noexcept
1471 { return std::move(_M_get()); }
1472
1473 template<typename _Up> friend class optional;
1474
1475#if __cpp_lib_optional >= 202110L // C++23
1476 template<typename _Fn, typename _Value>
1477 explicit constexpr
1478 optional(_Optional_func<_Fn> __f, _Value&& __v)
1479 {
1480 this->_M_payload._M_apply(__f, std::forward<_Value>(__v));
1481 }
1482#endif
1483 };
1484
1485#if __cpp_lib_optional >= 202506L // C++26
1486 template<typename _Tp>
1487 class optional<_Tp&>
1488 {
1489 static_assert(__is_valid_contained_type_for_optional<_Tp&>);
1490
1491 public:
1492 using value_type = _Tp;
1493 using iterator = __gnu_cxx::__normal_iterator<_Tp*, optional>;
1494
1495 // Constructors.
1496 constexpr optional() noexcept = default;
1497 constexpr optional(nullopt_t) noexcept : optional() {}
1498 constexpr optional(const optional&) noexcept = default;
1499
1500 template<typename _Arg>
1501 requires is_constructible_v<_Tp&, _Arg>
1502 && (!reference_constructs_from_temporary_v<_Tp&, _Arg>)
1503 explicit constexpr
1504 optional(in_place_t, _Arg&& __arg)
1505 {
1506 __convert_ref_init_val(std::forward<_Arg>(__arg));
1507 }
1508
1509 template<typename _Up>
1510 requires (!is_same_v<remove_cvref_t<_Up>, optional>)
1511 && (!is_same_v<remove_cvref_t<_Up>, in_place_t>)
1512 && is_constructible_v<_Tp&, _Up>
1513 && (!reference_constructs_from_temporary_v<_Tp&, _Up>)
1514 explicit(!is_convertible_v<_Up, _Tp&>)
1515 constexpr
1516 optional(_Up&& __u)
1517 noexcept(is_nothrow_constructible_v<_Tp&, _Up>)
1518 {
1519 __convert_ref_init_val(std::forward<_Up>(__u));
1520 }
1521
1522 template<typename _Up>
1523 requires (!is_same_v<remove_cvref_t<_Up>, optional>)
1524 && (!is_same_v<remove_cvref_t<_Up>, in_place_t>)
1525 && is_constructible_v<_Tp&, _Up>
1526 && reference_constructs_from_temporary_v<_Tp&, _Up>
1527 explicit(!is_convertible_v<_Up, _Tp&>)
1528 constexpr
1529 optional(_Up&& __u) = delete;
1530
1531 // optional<U> &
1532 template<typename _Up>
1533 requires (!is_same_v<remove_cv_t<_Tp>, optional<_Up>>)
1534 && (!is_same_v<_Tp&, _Up>)
1535 && is_constructible_v<_Tp&, _Up&>
1536 && (!reference_constructs_from_temporary_v<_Tp&, _Up&>)
1537 explicit(!is_convertible_v<_Up&, _Tp&>)
1538 constexpr
1539 optional(optional<_Up>& __rhs)
1540 noexcept(is_nothrow_constructible_v<_Tp&, _Up&>)
1541 {
1542 if (__rhs)
1543 __convert_ref_init_val(__rhs._M_fwd());
1544 }
1545
1546 template<typename _Up>
1547 requires (!is_same_v<remove_cv_t<_Tp>, optional<_Up>>)
1548 && (!is_same_v<_Tp&, _Up>)
1549 && is_constructible_v<_Tp&, _Up&>
1550 && reference_constructs_from_temporary_v<_Tp&, _Up&>
1551 explicit(!is_convertible_v<_Up&, _Tp&>)
1552 constexpr
1553 optional(optional<_Up>& __rhs) = delete;
1554
1555 // const optional<U>&
1556 template<typename _Up>
1557 requires (!is_same_v<remove_cv_t<_Tp>, optional<_Up>>)
1558 && (!is_same_v<_Tp&, _Up>)
1559 && is_constructible_v<_Tp&, const _Up&>
1560 && (!reference_constructs_from_temporary_v<_Tp&, const _Up&>)
1561 explicit(!is_convertible_v<const _Up&, _Tp&>)
1562 constexpr
1563 optional(const optional<_Up>& __rhs)
1564 noexcept(is_nothrow_constructible_v<_Tp&, _Up&>)
1565 {
1566 if (__rhs)
1567 __convert_ref_init_val(__rhs._M_fwd());
1568 }
1569
1570 template<typename _Up>
1571 requires (!is_same_v<remove_cv_t<_Tp>, optional<_Up>>)
1572 && (!is_same_v<_Tp&, _Up>)
1573 && is_constructible_v<_Tp&, const _Up&>
1574 && reference_constructs_from_temporary_v<_Tp&, const _Up&>
1575 explicit(!is_convertible_v<const _Up&, _Tp&>)
1576 constexpr
1577 optional(const optional<_Up>& __rhs) = delete;
1578
1579 // optional<U>&&
1580 template<typename _Up>
1581 requires (!is_same_v<remove_cv_t<_Tp>, optional<_Up>>)
1582 && (!is_same_v<_Tp&, _Up>)
1583 && is_constructible_v<_Tp&, _Up>
1584 && (!reference_constructs_from_temporary_v<_Tp&, _Up>)
1585 explicit(!is_convertible_v<_Up, _Tp&>)
1586 constexpr
1587 optional(optional<_Up>&& __rhs)
1588 noexcept(is_nothrow_constructible_v<_Tp&, _Up>)
1589 {
1590 if (__rhs)
1591 __convert_ref_init_val(std::move(__rhs)._M_fwd());
1592 }
1593
1594 template<typename _Up>
1595 requires (!is_same_v<remove_cv_t<_Tp>, optional<_Up>>)
1596 && (!is_same_v<_Tp&, _Up>)
1597 && is_constructible_v<_Tp&, _Up>
1598 && reference_constructs_from_temporary_v<_Tp&, _Up>
1599 explicit(!is_convertible_v<_Up, _Tp&>)
1600 constexpr
1601 optional(optional<_Up>&& __rhs) = delete;
1602
1603 // const optional<U>&&
1604 template<typename _Up>
1605 requires (!is_same_v<remove_cv_t<_Tp>, optional<_Up>>)
1606 && (!is_same_v<_Tp&, _Up>)
1607 && is_constructible_v<_Tp&, const _Up>
1608 && (!reference_constructs_from_temporary_v<_Tp&, _Up>)
1609 explicit(!is_convertible_v<const _Up, _Tp&>)
1610 constexpr
1611 optional(const optional<_Up>&& __rhs)
1612 noexcept(is_nothrow_constructible_v<_Tp&, const _Up>)
1613 {
1614 if (__rhs)
1615 __convert_ref_init_val(std::move(__rhs)._M_fwd());
1616 }
1617
1618 template<typename _Up>
1619 requires (!is_same_v<remove_cv_t<_Tp>, optional<_Up>>)
1620 && (!is_same_v<_Tp&, _Up>)
1621 && is_constructible_v<_Tp&, const _Up>
1622 && reference_constructs_from_temporary_v<_Tp&, const _Up>
1623 explicit(!is_convertible_v<const _Up, _Tp&>)
1624 constexpr
1625 optional(const optional<_Up>&& __rhs) = delete;
1626
1627 constexpr ~optional() = default;
1628
1629 // Assignment.
1630 constexpr optional& operator=(nullopt_t) noexcept
1631 {
1632 _M_val = nullptr;
1633 return *this;
1634 }
1635
1636 constexpr optional& operator=(const optional&) noexcept = default;
1637
1638 template<typename _Up>
1639 requires is_constructible_v<_Tp&, _Up>
1640 && (!reference_constructs_from_temporary_v<_Tp&, _Up>)
1641 constexpr _Tp&
1642 emplace(_Up&& __u)
1643 noexcept(is_nothrow_constructible_v<_Tp&, _Up>)
1644 {
1645 __convert_ref_init_val(std::forward<_Up>(__u));
1646 // _GLIBCXX_RESOLVE_LIB_DEFECTS
1647 // 4300. Missing Returns: element in optional<T&>::emplace
1648 return *_M_val;
1649 }
1650
1651 // Swap.
1652 constexpr void swap(optional& __rhs) noexcept
1653 { std::swap(_M_val, __rhs._M_val); }
1654
1655 // Iterator support.
1656 constexpr iterator begin() const noexcept
1657 {
1658 return iterator(_M_val);
1659 }
1660
1661 constexpr iterator end() const noexcept
1662 {
1663 return begin() + has_value();
1664 }
1665
1666 // Observers.
1667 constexpr _Tp* operator->() const noexcept
1668 {
1669 __glibcxx_assert(_M_val); // hardened precondition
1670 return _M_val;
1671 }
1672
1673 constexpr _Tp& operator*() const noexcept
1674 {
1675 __glibcxx_assert(_M_val); // hardened precondition
1676 return *_M_val;
1677 }
1678
1679 constexpr explicit operator bool() const noexcept
1680 {
1681 return _M_val;
1682 }
1683
1684 constexpr bool has_value() const noexcept
1685 {
1686 return _M_val;
1687 }
1688
1689 constexpr _Tp& value() const
1690 {
1691 if (_M_val)
1692 return *_M_val;
1693 __throw_bad_optional_access();
1694 }
1695
1696 // _GLIBCXX_RESOLVE_LIB_DEFECTS
1697 // 4304. std::optional<NonReturnable&> is ill-formed due to value_or
1698 template<typename _Up = remove_cv_t<_Tp>>
1699 requires is_object_v<_Tp> && (!is_array_v<_Tp>)
1700 constexpr decay_t<_Tp>
1701 value_or(_Up&& __u) const
1702 {
1703 using _Xp = remove_cv_t<_Tp>;
1704 static_assert(is_constructible_v<_Xp, _Tp&>);
1705 static_assert(is_convertible_v<_Up, _Xp>);
1706 return _M_val ? *_M_val : static_cast<_Xp>(std::forward<_Up>(__u));
1707 }
1708
1709 // Monadic operations.
1710 template<typename _Fn>
1711 constexpr auto
1712 and_then(_Fn&& __f) const
1713 {
1714 using _Up = remove_cvref_t<invoke_result_t<_Fn, _Tp&>>;
1715 static_assert(__is_optional_v<_Up>,
1716 "the function passed to std::optional<T&>::and_then "
1717 "must return a std::optional");
1718 if (has_value())
1719 return std::__invoke(std::forward<_Fn>(__f), *_M_val);
1720 else
1721 return _Up();
1722 }
1723
1724 template<typename _Fn>
1725 constexpr
1726 optional<remove_cv_t<invoke_result_t<_Fn, _Tp&>>>
1727 transform(_Fn&& __f) const
1728 {
1729 using _Up = remove_cv_t<invoke_result_t<_Fn, _Tp&>>;
1730 if (has_value())
1731 return optional<_Up>(_Optional_func<_Fn>{__f}, *_M_val);
1732 else
1733 return optional<_Up>();
1734 }
1735
1736 template<typename _Fn>
1737 requires invocable<_Fn>
1738 constexpr
1739 optional
1740 or_else(_Fn&& __f) const
1741 {
1742 static_assert(is_same_v<remove_cvref_t<invoke_result_t<_Fn>>, optional>,
1743 "the function passed to std::optional<T&>::or_else "
1744 "must return a std::optional<T&>");
1745 // _GLIBCXX_RESOLVE_LIB_DEFECTS
1746 // 4367. Improve optional<T&>::or_else
1747 if (has_value())
1748 return *this;
1749 else
1750 return std::forward<_Fn>(__f)();
1751 }
1752
1753 // Modifiers.
1754 constexpr void reset() noexcept
1755 {
1756 _M_val = nullptr;
1757 }
1758
1759 private:
1760 _Tp *_M_val = nullptr;
1761
1762 [[__gnu__::__always_inline__]]
1763 constexpr _Tp&
1764 _M_fwd() const noexcept
1765 { return *_M_val; }
1766
1767 template<typename _Up> friend class optional;
1768
1769 template<typename _Up>
1770 constexpr
1771 void
1772 __convert_ref_init_val(_Up&& __u)
1773 noexcept
1774 {
1775 _Tp& __r(std::forward<_Up>(__u));
1776 _M_val = std::addressof(__r);
1777 }
1778
1779 template<typename _Fn, typename _Value>
1780 explicit constexpr
1781 optional(_Optional_func<_Fn> __f, _Value&& __v)
1782 {
1783 _Tp& __r = std::__invoke(std::forward<_Fn>(__f._M_f), std::forward<_Value>(__v));
1784 _M_val = std::addressof(__r);
1785 }
1786 };
1787#endif // __cpp_lib_optional >= 202506L
1788
1789 template<typename _Tp>
1790 using __optional_relop_t =
1791 enable_if_t<is_convertible_v<_Tp, bool>, bool>;
1792
1793 template<typename _Tp, typename _Up>
1794 using __optional_eq_t = __optional_relop_t<
1795 decltype(std::declval<const _Tp&>() == std::declval<const _Up&>())
1796 >;
1797
1798 template<typename _Tp, typename _Up>
1799 using __optional_ne_t = __optional_relop_t<
1800 decltype(std::declval<const _Tp&>() != std::declval<const _Up&>())
1801 >;
1802
1803 template<typename _Tp, typename _Up>
1804 using __optional_lt_t = __optional_relop_t<
1805 decltype(std::declval<const _Tp&>() < std::declval<const _Up&>())
1806 >;
1807
1808 template<typename _Tp, typename _Up>
1809 using __optional_gt_t = __optional_relop_t<
1810 decltype(std::declval<const _Tp&>() > std::declval<const _Up&>())
1811 >;
1812
1813 template<typename _Tp, typename _Up>
1814 using __optional_le_t = __optional_relop_t<
1815 decltype(std::declval<const _Tp&>() <= std::declval<const _Up&>())
1816 >;
1817
1818 template<typename _Tp, typename _Up>
1819 using __optional_ge_t = __optional_relop_t<
1820 decltype(std::declval<const _Tp&>() >= std::declval<const _Up&>())
1821 >;
1822
1823 // Comparisons between optional values.
1824 template<typename _Tp, typename _Up>
1825 constexpr auto
1826 operator==(const optional<_Tp>& __lhs, const optional<_Up>& __rhs)
1827 -> __optional_eq_t<_Tp, _Up>
1828 {
1829 return static_cast<bool>(__lhs) == static_cast<bool>(__rhs)
1830 && (!__lhs || *__lhs == *__rhs);
1831 }
1832
1833 template<typename _Tp, typename _Up>
1834 constexpr auto
1835 operator!=(const optional<_Tp>& __lhs, const optional<_Up>& __rhs)
1836 -> __optional_ne_t<_Tp, _Up>
1837 {
1838 return static_cast<bool>(__lhs) != static_cast<bool>(__rhs)
1839 || (static_cast<bool>(__lhs) && *__lhs != *__rhs);
1840 }
1841
1842 template<typename _Tp, typename _Up>
1843 constexpr auto
1844 operator<(const optional<_Tp>& __lhs, const optional<_Up>& __rhs)
1845 -> __optional_lt_t<_Tp, _Up>
1846 {
1847 return static_cast<bool>(__rhs) && (!__lhs || *__lhs < *__rhs);
1848 }
1849
1850 template<typename _Tp, typename _Up>
1851 constexpr auto
1852 operator>(const optional<_Tp>& __lhs, const optional<_Up>& __rhs)
1853 -> __optional_gt_t<_Tp, _Up>
1854 {
1855 return static_cast<bool>(__lhs) && (!__rhs || *__lhs > *__rhs);
1856 }
1857
1858 template<typename _Tp, typename _Up>
1859 constexpr auto
1860 operator<=(const optional<_Tp>& __lhs, const optional<_Up>& __rhs)
1861 -> __optional_le_t<_Tp, _Up>
1862 {
1863 return !__lhs || (static_cast<bool>(__rhs) && *__lhs <= *__rhs);
1864 }
1865
1866 template<typename _Tp, typename _Up>
1867 constexpr auto
1868 operator>=(const optional<_Tp>& __lhs, const optional<_Up>& __rhs)
1869 -> __optional_ge_t<_Tp, _Up>
1870 {
1871 return !__rhs || (static_cast<bool>(__lhs) && *__lhs >= *__rhs);
1872 }
1873
1874#ifdef __cpp_lib_three_way_comparison
1875 template<typename _Tp, three_way_comparable_with<_Tp> _Up>
1876 [[nodiscard]]
1877 constexpr compare_three_way_result_t<_Tp, _Up>
1878 operator<=>(const optional<_Tp>& __x, const optional<_Up>& __y)
1879 {
1880 return __x && __y ? *__x <=> *__y : bool(__x) <=> bool(__y);
1881 }
1882#endif
1883
1884 // Comparisons with nullopt.
1885 template<typename _Tp>
1886 [[nodiscard]]
1887 constexpr bool
1888 operator==(const optional<_Tp>& __lhs, nullopt_t) noexcept
1889 { return !__lhs; }
1890
1891#ifdef __cpp_lib_three_way_comparison
1892 template<typename _Tp>
1893 [[nodiscard]]
1894 constexpr strong_ordering
1895 operator<=>(const optional<_Tp>& __x, nullopt_t) noexcept
1896 { return bool(__x) <=> false; }
1897#else
1898 template<typename _Tp>
1899 constexpr bool
1900 operator==(nullopt_t, const optional<_Tp>& __rhs) noexcept
1901 { return !__rhs; }
1902
1903 template<typename _Tp>
1904 constexpr bool
1905 operator!=(const optional<_Tp>& __lhs, nullopt_t) noexcept
1906 { return static_cast<bool>(__lhs); }
1907
1908 template<typename _Tp>
1909 constexpr bool
1910 operator!=(nullopt_t, const optional<_Tp>& __rhs) noexcept
1911 { return static_cast<bool>(__rhs); }
1912
1913 template<typename _Tp>
1914 constexpr bool
1915 operator<(const optional<_Tp>& /* __lhs */, nullopt_t) noexcept
1916 { return false; }
1917
1918 template<typename _Tp>
1919 constexpr bool
1920 operator<(nullopt_t, const optional<_Tp>& __rhs) noexcept
1921 { return static_cast<bool>(__rhs); }
1922
1923 template<typename _Tp>
1924 constexpr bool
1925 operator>(const optional<_Tp>& __lhs, nullopt_t) noexcept
1926 { return static_cast<bool>(__lhs); }
1927
1928 template<typename _Tp>
1929 constexpr bool
1930 operator>(nullopt_t, const optional<_Tp>& /* __rhs */) noexcept
1931 { return false; }
1932
1933 template<typename _Tp>
1934 constexpr bool
1935 operator<=(const optional<_Tp>& __lhs, nullopt_t) noexcept
1936 { return !__lhs; }
1937
1938 template<typename _Tp>
1939 constexpr bool
1940 operator<=(nullopt_t, const optional<_Tp>& /* __rhs */) noexcept
1941 { return true; }
1942
1943 template<typename _Tp>
1944 constexpr bool
1945 operator>=(const optional<_Tp>& /* __lhs */, nullopt_t) noexcept
1946 { return true; }
1947
1948 template<typename _Tp>
1949 constexpr bool
1950 operator>=(nullopt_t, const optional<_Tp>& __rhs) noexcept
1951 { return !__rhs; }
1952#endif // three-way-comparison
1953
1954#if __cpp_lib_concepts
1955 // _GLIBCXX_RESOLVE_LIB_DEFECTS
1956 // 4072. std::optional comparisons: constrain harder
1957# define _REQUIRES_NOT_OPTIONAL(T) requires (!__is_optional_v<T>)
1958#else
1959# define _REQUIRES_NOT_OPTIONAL(T)
1960#endif
1961
1962 // Comparisons with value type.
1963 template<typename _Tp, typename _Up>
1964 _REQUIRES_NOT_OPTIONAL(_Up)
1965 constexpr auto
1966 operator== [[nodiscard]] (const optional<_Tp>& __lhs, const _Up& __rhs)
1967 -> __optional_eq_t<_Tp, _Up>
1968 { return __lhs && *__lhs == __rhs; }
1969
1970 template<typename _Tp, typename _Up>
1971 _REQUIRES_NOT_OPTIONAL(_Tp)
1972 constexpr auto
1973 operator== [[nodiscard]] (const _Tp& __lhs, const optional<_Up>& __rhs)
1974 -> __optional_eq_t<_Tp, _Up>
1975 { return __rhs && __lhs == *__rhs; }
1976
1977 template<typename _Tp, typename _Up>
1978 _REQUIRES_NOT_OPTIONAL(_Up)
1979 constexpr auto
1980 operator!= [[nodiscard]] (const optional<_Tp>& __lhs, const _Up& __rhs)
1981 -> __optional_ne_t<_Tp, _Up>
1982 { return !__lhs || *__lhs != __rhs; }
1983
1984 template<typename _Tp, typename _Up>
1985 _REQUIRES_NOT_OPTIONAL(_Tp)
1986 constexpr auto
1987 operator!= [[nodiscard]] (const _Tp& __lhs, const optional<_Up>& __rhs)
1988 -> __optional_ne_t<_Tp, _Up>
1989 { return !__rhs || __lhs != *__rhs; }
1990
1991 template<typename _Tp, typename _Up>
1992 _REQUIRES_NOT_OPTIONAL(_Up)
1993 constexpr auto
1994 operator< [[nodiscard]] (const optional<_Tp>& __lhs, const _Up& __rhs)
1995 -> __optional_lt_t<_Tp, _Up>
1996 { return !__lhs || *__lhs < __rhs; }
1997
1998 template<typename _Tp, typename _Up>
1999 _REQUIRES_NOT_OPTIONAL(_Tp)
2000 constexpr auto
2001 operator< [[nodiscard]] (const _Tp& __lhs, const optional<_Up>& __rhs)
2002 -> __optional_lt_t<_Tp, _Up>
2003 { return __rhs && __lhs < *__rhs; }
2004
2005 template<typename _Tp, typename _Up>
2006 _REQUIRES_NOT_OPTIONAL(_Up)
2007 constexpr auto
2008 operator> [[nodiscard]] (const optional<_Tp>& __lhs, const _Up& __rhs)
2009 -> __optional_gt_t<_Tp, _Up>
2010 { return __lhs && *__lhs > __rhs; }
2011
2012 template<typename _Tp, typename _Up>
2013 _REQUIRES_NOT_OPTIONAL(_Tp)
2014 constexpr auto
2015 operator> [[nodiscard]] (const _Tp& __lhs, const optional<_Up>& __rhs)
2016 -> __optional_gt_t<_Tp, _Up>
2017 { return !__rhs || __lhs > *__rhs; }
2018
2019 template<typename _Tp, typename _Up>
2020 _REQUIRES_NOT_OPTIONAL(_Up)
2021 constexpr auto
2022 operator<= [[nodiscard]] (const optional<_Tp>& __lhs, const _Up& __rhs)
2023 -> __optional_le_t<_Tp, _Up>
2024 { return !__lhs || *__lhs <= __rhs; }
2025
2026 template<typename _Tp, typename _Up>
2027 _REQUIRES_NOT_OPTIONAL(_Tp)
2028 constexpr auto
2029 operator<= [[nodiscard]] (const _Tp& __lhs, const optional<_Up>& __rhs)
2030 -> __optional_le_t<_Tp, _Up>
2031 { return __rhs && __lhs <= *__rhs; }
2032
2033 template<typename _Tp, typename _Up>
2034 _REQUIRES_NOT_OPTIONAL(_Up)
2035 constexpr auto
2036 operator>= [[nodiscard]] (const optional<_Tp>& __lhs, const _Up& __rhs)
2037 -> __optional_ge_t<_Tp, _Up>
2038 { return __lhs && *__lhs >= __rhs; }
2039
2040 template<typename _Tp, typename _Up>
2041 _REQUIRES_NOT_OPTIONAL(_Tp)
2042 constexpr auto
2043 operator>= [[nodiscard]] (const _Tp& __lhs, const optional<_Up>& __rhs)
2044 -> __optional_ge_t<_Tp, _Up>
2045 { return !__rhs || __lhs >= *__rhs; }
2046
2047#ifdef __cpp_lib_three_way_comparison
2048 // _GLIBCXX_RESOLVE_LIB_DEFECTS
2049 // 3746. optional's spaceship with U with a type derived from optional
2050 // causes infinite constraint meta-recursion
2051 template<typename _Tp>
2052 concept __is_derived_from_optional = requires (const _Tp& __t) {
2053 []<typename _Up>(const optional<_Up>&){ }(__t);
2054 };
2055
2056 template<typename _Tp, typename _Up>
2057 requires (!__is_derived_from_optional<_Up>)
2058 && requires { typename compare_three_way_result_t<_Tp, _Up>; }
2059 && three_way_comparable_with<_Tp, _Up>
2060 constexpr compare_three_way_result_t<_Tp, _Up>
2061 operator<=> [[nodiscard]] (const optional<_Tp>& __x, const _Up& __v)
2062 { return bool(__x) ? *__x <=> __v : strong_ordering::less; }
2063#endif
2064
2065 // Swap and creation functions.
2066
2067 // _GLIBCXX_RESOLVE_LIB_DEFECTS
2068 // 2748. swappable traits for optionals
2069 template<typename _Tp>
2070 _GLIBCXX20_CONSTEXPR
2071 inline enable_if_t<is_move_constructible_v<_Tp> && is_swappable_v<_Tp>>
2072 swap(optional<_Tp>& __lhs, optional<_Tp>& __rhs)
2073 noexcept(noexcept(__lhs.swap(__rhs)))
2074 { __lhs.swap(__rhs); }
2075
2076#if __cpp_lib_optional >= 202506L
2077 // We deviate from standard, that do not declared separate swap overload
2078 // from optional<T&>.
2079 template<typename _Tp>
2080 constexpr void
2081 swap(optional<_Tp&>& __lhs, optional<_Tp&>& __rhs) noexcept
2082 { __lhs.swap(__rhs); }
2083#endif
2084
2085 // _GLIBCXX_RESOLVE_LIB_DEFECTS
2086 // 2766. Swapping non-swappable types
2087 template<typename _Tp>
2088 enable_if_t<!(is_move_constructible_v<_Tp> && is_swappable_v<_Tp>)>
2089 swap(optional<_Tp>&, optional<_Tp>&) = delete;
2090
2091#if __cpp_lib_optional >= 202506L
2092 template<int = 0, typename _Tp>
2093#else
2094 template<typename _Tp>
2095#endif
2096 constexpr
2097 enable_if_t<is_constructible_v<decay_t<_Tp>, _Tp>,
2098 optional<decay_t<_Tp>>>
2099 make_optional(_Tp&& __t)
2100 noexcept(is_nothrow_constructible_v<optional<decay_t<_Tp>>, _Tp>)
2101 { return optional<decay_t<_Tp>>( std::forward<_Tp>(__t) ); }
2102
2103 template<typename _Tp, typename... _Args>
2104 constexpr
2105 enable_if_t<is_constructible_v<_Tp, _Args...>,
2106 optional<_Tp>>
2107 make_optional(_Args&&... __args)
2108 noexcept(is_nothrow_constructible_v<_Tp, _Args...>)
2109 { return optional<_Tp>( in_place, std::forward<_Args>(__args)... ); }
2110
2111 template<typename _Tp, typename _Up, typename... _Args>
2112 constexpr
2113 enable_if_t<is_constructible_v<_Tp, initializer_list<_Up>&, _Args...>,
2114 optional<_Tp>>
2115 make_optional(initializer_list<_Up> __il, _Args&&... __args)
2116 noexcept(is_nothrow_constructible_v<_Tp, initializer_list<_Up>&, _Args...>)
2117 { return optional<_Tp>( in_place, __il, std::forward<_Args>(__args)... ); }
2118
2119 // Hash.
2120
2121 template<typename _Tp, typename _Up = remove_const_t<_Tp>>
2122 struct __optional_hash
2123#if ! _GLIBCXX_INLINE_VERSION
2124 : public __hash_empty_base<_Up>
2125#endif
2126 {
2127#if __cplusplus < 202002L
2128 using result_type [[__deprecated__]] = size_t;
2129 using argument_type [[__deprecated__]] = optional<_Tp>;
2130#endif
2131
2132 size_t
2133 operator()(const optional<_Tp>& __t) const
2134 noexcept(noexcept(hash<_Up>{}(*__t)))
2135 {
2136 // We pick an arbitrary hash for disengaged optionals which hopefully
2137 // usual values of _Tp won't typically hash to.
2138 constexpr size_t __magic_disengaged_hash = static_cast<size_t>(-3333);
2139 return __t ? hash<_Up>{}(*__t) : __magic_disengaged_hash;
2140 }
2141 };
2142
2143 template<typename _Tp>
2144 struct hash<optional<_Tp>>
2145 // hash for optional<T&> is disabled because is_hash_enabled_for<T&> is false
2146 : public __conditional_t<__is_hash_enabled_for<remove_const_t<_Tp>>,
2147 __optional_hash<_Tp>,
2148 __hash_not_enabled<_Tp>>
2149 { };
2150
2151 template<typename _Tp>
2152 struct __is_fast_hash<hash<optional<_Tp>>> : __is_fast_hash<hash<_Tp>>
2153 { };
2154
2155 /// @}
2156
2157#if __cpp_deduction_guides >= 201606
2158 template <typename _Tp> optional(_Tp) -> optional<_Tp>;
2159#endif
2160
2161#ifdef __cpp_lib_optional_range_support // >= C++26
2162 template<typename _Tp>
2163 inline constexpr bool
2164 ranges::enable_view<optional<_Tp>> = true;
2165
2166 template<typename _Tp>
2167 inline constexpr range_format
2168 format_kind<optional<_Tp>> = range_format::disabled;
2169#endif // __cpp_lib_optional_range_support
2170
2171#undef _GLIBCXX_USE_CONSTRAINTS_FOR_OPTIONAL
2172
2173_GLIBCXX_END_NAMESPACE_VERSION
2174} // namespace std
2175
2176#endif // __cpp_lib_optional
2177
2178#endif // _GLIBCXX_OPTIONAL