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 /**
781 * @brief Class template for optional values.
782 */
783 template<typename _Tp>
784 class optional
785 : private _Optional_base<_Tp>,
786 private _Enable_copy_move<
787 // Copy constructor.
788 is_copy_constructible_v<_Tp>,
789 // Copy assignment.
790 __and_v<is_copy_constructible<_Tp>, is_copy_assignable<_Tp>>,
791 // Move constructor.
792 is_move_constructible_v<_Tp>,
793 // Move assignment.
794 __and_v<is_move_constructible<_Tp>, is_move_assignable<_Tp>>,
795 // Unique tag type.
796 optional<_Tp>>
797 {
798 static_assert(!is_same_v<remove_cv_t<_Tp>, nullopt_t>);
799 static_assert(!is_same_v<remove_cv_t<_Tp>, in_place_t>);
800 static_assert(is_object_v<_Tp> && !is_array_v<_Tp>);
801
802 private:
803 using _Base = _Optional_base<_Tp>;
804
805 // SFINAE helpers
806
807 // _GLIBCXX_RESOLVE_LIB_DEFECTS
808 // 3836. std::expected<bool, E1> conversion constructor
809 // expected(const expected<U, G>&) should take precedence over
810 // expected(U&&) with operator bool
811#ifdef _GLIBCXX_USE_CONSTRAINTS_FOR_OPTIONAL
812 template<typename _From, typename = remove_cv_t<_Tp>>
813 static constexpr bool __not_constructing_bool_from_optional
814 = true;
815
816 // If T is cv bool, remove_cvref_t<U> is not a specialization of optional
817 // i.e. do not initialize a bool from optional<U>::operator bool().
818 template<typename _From>
819 static constexpr bool
820 __not_constructing_bool_from_optional<_From, bool>
821 = !__is_optional_v<remove_cvref_t<_From>>;
822
823 // If T is not cv bool, converts-from-any-cvref<T, optional<U>> is false.
824 // The constructor that converts from optional<U> is disabled if the
825 // contained value can be initialized from optional<U>, so that the
826 // optional(U&&) constructor can be used instead.
827 template<typename _From, typename = remove_cv_t<_Tp>>
828 static constexpr bool __construct_from_contained_value
829 = !__converts_from_optional<_Tp, _From>::value;
830
831 // However, optional<U> can always be converted to bool, so don't apply
832 // this constraint when T is cv bool.
833 template<typename _From>
834 static constexpr bool __construct_from_contained_value<_From, bool>
835 = true;
836#else
837 template<typename _From, typename = remove_cv_t<_Tp>>
838 struct __not_constructing_bool_from_optional
839 : true_type
840 { };
841
842 template<typename _From>
843 struct __not_constructing_bool_from_optional<_From, bool>
844 : bool_constant<!__is_optional_v<__remove_cvref_t<_From>>>
845 { };
846
847 template<typename _From, typename = remove_cv_t<_Tp>>
848 struct __construct_from_contained_value
849 : __not_<__converts_from_optional<_Tp, _From>>
850 { };
851
852 template<typename _From>
853 struct __construct_from_contained_value<_From, bool>
854 : true_type
855 { };
856
857 template<typename _Up>
858 using __not_self = __not_<is_same<optional, __remove_cvref_t<_Up>>>;
859 template<typename _Up>
860 using __not_tag = __not_<is_same<in_place_t, __remove_cvref_t<_Up>>>;
861 template<typename... _Cond>
862 using _Requires = enable_if_t<__and_v<_Cond...>, bool>;
863#endif
864
865 public:
866 using value_type = _Tp;
867#ifdef __cpp_lib_optional_range_support // >= C++26
868 using iterator = __gnu_cxx::__normal_iterator<_Tp*, optional>;
869 using const_iterator = __gnu_cxx::__normal_iterator<const _Tp*, optional>;
870#endif
871
872 constexpr optional() noexcept { }
873
874 constexpr optional(nullopt_t) noexcept { }
875
876 // Converting constructors for engaged optionals.
877#ifdef _GLIBCXX_USE_CONSTRAINTS_FOR_OPTIONAL
878 template<typename _Up = remove_cv_t<_Tp>>
879 requires (!is_same_v<optional, remove_cvref_t<_Up>>)
880 && (!is_same_v<in_place_t, remove_cvref_t<_Up>>)
881 && is_constructible_v<_Tp, _Up>
882 && __not_constructing_bool_from_optional<_Up>
883 constexpr explicit(!is_convertible_v<_Up, _Tp>)
884 optional(_Up&& __t)
885 noexcept(is_nothrow_constructible_v<_Tp, _Up>)
886 : _Base(std::in_place, std::forward<_Up>(__t)) { }
887
888 template<typename _Up>
889 requires (!is_same_v<_Tp, _Up>)
890 && is_constructible_v<_Tp, const _Up&>
891 && __construct_from_contained_value<_Up>
892 constexpr explicit(!is_convertible_v<const _Up&, _Tp>)
893 optional(const optional<_Up>& __t)
894 noexcept(is_nothrow_constructible_v<_Tp, const _Up&>)
895 {
896 if (__t)
897 emplace(__t._M_get());
898 }
899
900 template<typename _Up>
901 requires (!is_same_v<_Tp, _Up>)
902 && is_constructible_v<_Tp, _Up>
903 && __construct_from_contained_value<_Up>
904 constexpr explicit(!is_convertible_v<_Up, _Tp>)
905 optional(optional<_Up>&& __t)
906 noexcept(is_nothrow_constructible_v<_Tp, _Up>)
907 {
908 if (__t)
909 emplace(std::move(__t._M_get()));
910 }
911
912 template<typename... _Args>
913 requires is_constructible_v<_Tp, _Args...>
914 explicit constexpr
915 optional(in_place_t, _Args&&... __args)
916 noexcept(is_nothrow_constructible_v<_Tp, _Args...>)
917 : _Base(std::in_place, std::forward<_Args>(__args)...)
918 { }
919
920 template<typename _Up, typename... _Args>
921 requires is_constructible_v<_Tp, initializer_list<_Up>&, _Args...>
922 explicit constexpr
923 optional(in_place_t, initializer_list<_Up> __il, _Args&&... __args)
924 noexcept(is_nothrow_constructible_v<_Tp, initializer_list<_Up>&,
925 _Args...>)
926 : _Base(std::in_place, __il, std::forward<_Args>(__args)...)
927 { }
928#else
929 template<typename _Up = remove_cv_t<_Tp>,
930 _Requires<__not_self<_Up>, __not_tag<_Up>,
931 is_constructible<_Tp, _Up>,
932 is_convertible<_Up, _Tp>,
933 __not_constructing_bool_from_optional<_Up>> = true>
934 constexpr
935 optional(_Up&& __t)
936 noexcept(is_nothrow_constructible_v<_Tp, _Up>)
937 : _Base(std::in_place, std::forward<_Up>(__t)) { }
938
939 template<typename _Up = remove_cv_t<_Tp>,
940 _Requires<__not_self<_Up>, __not_tag<_Up>,
941 is_constructible<_Tp, _Up>,
942 __not_<is_convertible<_Up, _Tp>>,
943 __not_constructing_bool_from_optional<_Up>> = false>
944 explicit constexpr
945 optional(_Up&& __t)
946 noexcept(is_nothrow_constructible_v<_Tp, _Up>)
947 : _Base(std::in_place, std::forward<_Up>(__t)) { }
948
949 template<typename _Up,
950 _Requires<__not_<is_same<_Tp, _Up>>,
951 is_constructible<_Tp, const _Up&>,
952 is_convertible<const _Up&, _Tp>,
953 __construct_from_contained_value<_Up>> = true>
954 constexpr
955 optional(const optional<_Up>& __t)
956 noexcept(is_nothrow_constructible_v<_Tp, const _Up&>)
957 {
958 if (__t)
959 emplace(__t._M_get());
960 }
961
962 template<typename _Up,
963 _Requires<__not_<is_same<_Tp, _Up>>,
964 is_constructible<_Tp, const _Up&>,
965 __not_<is_convertible<const _Up&, _Tp>>,
966 __construct_from_contained_value<_Up>> = false>
967 explicit constexpr
968 optional(const optional<_Up>& __t)
969 noexcept(is_nothrow_constructible_v<_Tp, const _Up&>)
970 {
971 if (__t)
972 emplace(__t._M_get());
973 }
974
975 template<typename _Up,
976 _Requires<__not_<is_same<_Tp, _Up>>,
977 is_constructible<_Tp, _Up>,
978 is_convertible<_Up, _Tp>,
979 __construct_from_contained_value<_Up>> = true>
980 constexpr
981 optional(optional<_Up>&& __t)
982 noexcept(is_nothrow_constructible_v<_Tp, _Up>)
983 {
984 if (__t)
985 emplace(std::move(__t._M_get()));
986 }
987
988 template<typename _Up,
989 _Requires<__not_<is_same<_Tp, _Up>>,
990 is_constructible<_Tp, _Up>,
991 __not_<is_convertible<_Up, _Tp>>,
992 __construct_from_contained_value<_Up>> = false>
993 explicit constexpr
994 optional(optional<_Up>&& __t)
995 noexcept(is_nothrow_constructible_v<_Tp, _Up>)
996 {
997 if (__t)
998 emplace(std::move(__t._M_get()));
999 }
1000
1001 template<typename... _Args,
1002 _Requires<is_constructible<_Tp, _Args...>> = false>
1003 explicit constexpr
1004 optional(in_place_t, _Args&&... __args)
1005 noexcept(is_nothrow_constructible_v<_Tp, _Args...>)
1006 : _Base(std::in_place, std::forward<_Args>(__args)...) { }
1007
1008 template<typename _Up, typename... _Args,
1009 _Requires<is_constructible<_Tp,
1010 initializer_list<_Up>&,
1011 _Args...>> = false>
1012 explicit constexpr
1013 optional(in_place_t, initializer_list<_Up> __il, _Args&&... __args)
1014 noexcept(is_nothrow_constructible_v<_Tp, initializer_list<_Up>&,
1015 _Args...>)
1016 : _Base(std::in_place, __il, std::forward<_Args>(__args)...) { }
1017#endif
1018
1019 // Assignment operators.
1020 _GLIBCXX20_CONSTEXPR optional&
1021 operator=(nullopt_t) noexcept
1022 {
1023 this->_M_reset();
1024 return *this;
1025 }
1026
1027 template<typename _Up = remove_cv_t<_Tp>>
1028#ifdef _GLIBCXX_USE_CONSTRAINTS_FOR_OPTIONAL
1029 requires (!is_same_v<optional, remove_cvref_t<_Up>>)
1030 && (!(is_scalar_v<_Tp> && is_same_v<_Tp, decay_t<_Up>>))
1031 && is_constructible_v<_Tp, _Up>
1032 && is_assignable_v<_Tp&, _Up>
1033 constexpr optional&
1034#else
1035 enable_if_t<__and_v<__not_self<_Up>,
1036 __not_<__and_<is_scalar<_Tp>,
1037 is_same<_Tp, decay_t<_Up>>>>,
1038 is_constructible<_Tp, _Up>,
1039 is_assignable<_Tp&, _Up>>,
1040 optional&>
1041#endif
1042 operator=(_Up&& __u)
1043 noexcept(__and_v<is_nothrow_constructible<_Tp, _Up>,
1044 is_nothrow_assignable<_Tp&, _Up>>)
1045 {
1046 if (this->_M_is_engaged())
1047 this->_M_get() = std::forward<_Up>(__u);
1048 else
1049 this->_M_construct(std::forward<_Up>(__u));
1050
1051 return *this;
1052 }
1053
1054 template<typename _Up>
1055#ifdef _GLIBCXX_USE_CONSTRAINTS_FOR_OPTIONAL
1056 requires (!is_same_v<_Tp, _Up>)
1057 && is_constructible_v<_Tp, const _Up&>
1058 && is_assignable_v<_Tp&, const _Up&>
1059 && (!__converts_from_optional<_Tp, _Up>::value)
1060 && (!__assigns_from_optional<_Tp, _Up>::value)
1061 constexpr optional&
1062#else
1063 enable_if_t<__and_v<__not_<is_same<_Tp, _Up>>,
1064 is_constructible<_Tp, const _Up&>,
1065 is_assignable<_Tp&, const _Up&>,
1066 __not_<__converts_from_optional<_Tp, _Up>>,
1067 __not_<__assigns_from_optional<_Tp, _Up>>>,
1068 optional&>
1069#endif
1070 operator=(const optional<_Up>& __u)
1071 noexcept(__and_v<is_nothrow_constructible<_Tp, const _Up&>,
1072 is_nothrow_assignable<_Tp&, const _Up&>>)
1073 {
1074 if (__u)
1075 {
1076 if (this->_M_is_engaged())
1077 this->_M_get() = __u._M_get();
1078 else
1079 this->_M_construct(__u._M_get());
1080 }
1081 else
1082 {
1083 this->_M_reset();
1084 }
1085 return *this;
1086 }
1087
1088 template<typename _Up>
1089#ifdef _GLIBCXX_USE_CONSTRAINTS_FOR_OPTIONAL
1090 requires (!is_same_v<_Tp, _Up>)
1091 && is_constructible_v<_Tp, _Up>
1092 && is_assignable_v<_Tp&, _Up>
1093 && (!__converts_from_optional<_Tp, _Up>::value)
1094 && (!__assigns_from_optional<_Tp, _Up>::value)
1095 constexpr optional&
1096#else
1097 enable_if_t<__and_v<__not_<is_same<_Tp, _Up>>,
1098 is_constructible<_Tp, _Up>,
1099 is_assignable<_Tp&, _Up>,
1100 __not_<__converts_from_optional<_Tp, _Up>>,
1101 __not_<__assigns_from_optional<_Tp, _Up>>>,
1102 optional&>
1103#endif
1104 operator=(optional<_Up>&& __u)
1105 noexcept(__and_v<is_nothrow_constructible<_Tp, _Up>,
1106 is_nothrow_assignable<_Tp&, _Up>>)
1107 {
1108 if (__u)
1109 {
1110 if (this->_M_is_engaged())
1111 this->_M_get() = std::move(__u._M_get());
1112 else
1113 this->_M_construct(std::move(__u._M_get()));
1114 }
1115 else
1116 {
1117 this->_M_reset();
1118 }
1119
1120 return *this;
1121 }
1122
1123 template<typename... _Args>
1124 _GLIBCXX20_CONSTEXPR
1125 enable_if_t<is_constructible_v<_Tp, _Args...>, _Tp&>
1126 emplace(_Args&&... __args)
1127 noexcept(is_nothrow_constructible_v<_Tp, _Args...>)
1128 {
1129 this->_M_reset();
1130 this->_M_construct(std::forward<_Args>(__args)...);
1131 return this->_M_get();
1132 }
1133
1134 template<typename _Up, typename... _Args>
1135 _GLIBCXX20_CONSTEXPR
1136 enable_if_t<is_constructible_v<_Tp, initializer_list<_Up>&, _Args...>,
1137 _Tp&>
1138 emplace(initializer_list<_Up> __il, _Args&&... __args)
1139 noexcept(is_nothrow_constructible_v<_Tp, initializer_list<_Up>&,
1140 _Args...>)
1141 {
1142 this->_M_reset();
1143 this->_M_construct(__il, std::forward<_Args>(__args)...);
1144 return this->_M_get();
1145 }
1146
1147 // Destructor is implicit, implemented in _Optional_base.
1148
1149 // Swap.
1150 _GLIBCXX20_CONSTEXPR void
1151 swap(optional& __other)
1152 noexcept(is_nothrow_move_constructible_v<_Tp>
1153 && is_nothrow_swappable_v<_Tp>)
1154 {
1155 using std::swap;
1156
1157 if (this->_M_is_engaged() && __other._M_is_engaged())
1158 swap(this->_M_get(), __other._M_get());
1159 else if (this->_M_is_engaged())
1160 {
1161 __other._M_construct(std::move(this->_M_get()));
1162 this->_M_destruct();
1163 }
1164 else if (__other._M_is_engaged())
1165 {
1166 this->_M_construct(std::move(__other._M_get()));
1167 __other._M_destruct();
1168 }
1169 }
1170
1171#ifdef __cpp_lib_optional_range_support // >= C++26
1172 // Iterator support.
1173 constexpr iterator begin() noexcept
1174 {
1175 return iterator(
1176 this->_M_is_engaged() ? std::addressof(this->_M_get()) : nullptr
1177 );
1178 }
1179
1180 constexpr const_iterator begin() const noexcept
1181 {
1182 return const_iterator(
1183 this->_M_is_engaged() ? std::addressof(this->_M_get()) : nullptr
1184 );
1185 }
1186
1187 constexpr iterator end() noexcept
1188 {
1189 return begin() + has_value();
1190 }
1191
1192 constexpr const_iterator end() const noexcept
1193 {
1194 return begin() + has_value();
1195 }
1196#endif // __cpp_lib_optional_range_support
1197
1198 // Observers.
1199 constexpr const _Tp*
1200 operator->() const noexcept
1201 {
1202 __glibcxx_assert(this->_M_is_engaged());
1203 return std::__addressof(this->_M_get());
1204 }
1205
1206 constexpr _Tp*
1207 operator->() noexcept
1208 {
1209 __glibcxx_assert(this->_M_is_engaged());
1210 return std::__addressof(this->_M_get());
1211 }
1212
1213 constexpr const _Tp&
1214 operator*() const& noexcept
1215 {
1216 __glibcxx_assert(this->_M_is_engaged());
1217 return this->_M_get();
1218 }
1219
1220 constexpr _Tp&
1221 operator*()& noexcept
1222 {
1223 __glibcxx_assert(this->_M_is_engaged());
1224 return this->_M_get();
1225 }
1226
1227 constexpr _Tp&&
1228 operator*()&& noexcept
1229 {
1230 __glibcxx_assert(this->_M_is_engaged());
1231 return std::move(this->_M_get());
1232 }
1233
1234 constexpr const _Tp&&
1235 operator*() const&& noexcept
1236 {
1237 __glibcxx_assert(this->_M_is_engaged());
1238 return std::move(this->_M_get());
1239 }
1240
1241 constexpr explicit operator bool() const noexcept
1242 { return this->_M_is_engaged(); }
1243
1244 constexpr bool has_value() const noexcept
1245 { return this->_M_is_engaged(); }
1246
1247 constexpr const _Tp&
1248 value() const&
1249 {
1250 if (this->_M_is_engaged())
1251 return this->_M_get();
1252 __throw_bad_optional_access();
1253 }
1254
1255 constexpr _Tp&
1256 value()&
1257 {
1258 if (this->_M_is_engaged())
1259 return this->_M_get();
1260 __throw_bad_optional_access();
1261 }
1262
1263 constexpr _Tp&&
1264 value()&&
1265 {
1266 if (this->_M_is_engaged())
1267 return std::move(this->_M_get());
1268 __throw_bad_optional_access();
1269 }
1270
1271 constexpr const _Tp&&
1272 value() const&&
1273 {
1274 if (this->_M_is_engaged())
1275 return std::move(this->_M_get());
1276 __throw_bad_optional_access();
1277 }
1278
1279 template<typename _Up = remove_cv_t<_Tp>>
1280 constexpr _Tp
1281 value_or(_Up&& __u) const&
1282 {
1283 static_assert(is_copy_constructible_v<_Tp>);
1284 static_assert(is_convertible_v<_Up&&, _Tp>);
1285
1286 if (this->_M_is_engaged())
1287 return this->_M_get();
1288 else
1289 return static_cast<_Tp>(std::forward<_Up>(__u));
1290 }
1291
1292 template<typename _Up = remove_cv_t<_Tp>>
1293 constexpr _Tp
1294 value_or(_Up&& __u) &&
1295 {
1296 static_assert(is_move_constructible_v<_Tp>);
1297 static_assert(is_convertible_v<_Up&&, _Tp>);
1298
1299 if (this->_M_is_engaged())
1300 return std::move(this->_M_get());
1301 else
1302 return static_cast<_Tp>(std::forward<_Up>(__u));
1303 }
1304
1305#if __cpp_lib_optional >= 202110L // C++23
1306 // [optional.monadic]
1307
1308 template<typename _Fn>
1309 constexpr auto
1310 and_then(_Fn&& __f) &
1311 {
1312 using _Up = remove_cvref_t<invoke_result_t<_Fn, _Tp&>>;
1313 static_assert(__is_optional_v<remove_cvref_t<_Up>>,
1314 "the function passed to std::optional<T>::and_then "
1315 "must return a std::optional");
1316 if (has_value())
1317 return std::__invoke(std::forward<_Fn>(__f), _M_get());
1318 else
1319 return _Up();
1320 }
1321
1322 template<typename _Fn>
1323 constexpr auto
1324 and_then(_Fn&& __f) const &
1325 {
1326 using _Up = remove_cvref_t<invoke_result_t<_Fn, const _Tp&>>;
1327 static_assert(__is_optional_v<_Up>,
1328 "the function passed to std::optional<T>::and_then "
1329 "must return a std::optional");
1330 if (has_value())
1331 return std::__invoke(std::forward<_Fn>(__f), _M_get());
1332 else
1333 return _Up();
1334 }
1335
1336 template<typename _Fn>
1337 constexpr auto
1338 and_then(_Fn&& __f) &&
1339 {
1340 using _Up = remove_cvref_t<invoke_result_t<_Fn, _Tp>>;
1341 static_assert(__is_optional_v<remove_cvref_t<_Up>>,
1342 "the function passed to std::optional<T>::and_then "
1343 "must return a std::optional");
1344 if (has_value())
1345 return std::__invoke(std::forward<_Fn>(__f), std::move(_M_get()));
1346 else
1347 return _Up();
1348 }
1349
1350 template<typename _Fn>
1351 constexpr auto
1352 and_then(_Fn&& __f) const &&
1353 {
1354 using _Up = remove_cvref_t<invoke_result_t<_Fn, const _Tp>>;
1355 static_assert(__is_optional_v<remove_cvref_t<_Up>>,
1356 "the function passed to std::optional<T>::and_then "
1357 "must return a std::optional");
1358 if (has_value())
1359 return std::__invoke(std::forward<_Fn>(__f), std::move(_M_get()));
1360 else
1361 return _Up();
1362 }
1363
1364 template<typename _Fn>
1365 constexpr auto
1366 transform(_Fn&& __f) &
1367 {
1368 using _Up = remove_cv_t<invoke_result_t<_Fn, _Tp&>>;
1369 if (has_value())
1370 return optional<_Up>(_Optional_func<_Fn>{__f}, _M_get());
1371 else
1372 return optional<_Up>();
1373 }
1374
1375 template<typename _Fn>
1376 constexpr auto
1377 transform(_Fn&& __f) const &
1378 {
1379 using _Up = remove_cv_t<invoke_result_t<_Fn, const _Tp&>>;
1380 if (has_value())
1381 return optional<_Up>(_Optional_func<_Fn>{__f}, _M_get());
1382 else
1383 return optional<_Up>();
1384 }
1385
1386 template<typename _Fn>
1387 constexpr auto
1388 transform(_Fn&& __f) &&
1389 {
1390 using _Up = remove_cv_t<invoke_result_t<_Fn, _Tp>>;
1391 if (has_value())
1392 return optional<_Up>(_Optional_func<_Fn>{__f}, std::move(_M_get()));
1393 else
1394 return optional<_Up>();
1395 }
1396
1397 template<typename _Fn>
1398 constexpr auto
1399 transform(_Fn&& __f) const &&
1400 {
1401 using _Up = remove_cv_t<invoke_result_t<_Fn, const _Tp>>;
1402 if (has_value())
1403 return optional<_Up>(_Optional_func<_Fn>{__f}, std::move(_M_get()));
1404 else
1405 return optional<_Up>();
1406 }
1407
1408 template<typename _Fn> requires invocable<_Fn> && copy_constructible<_Tp>
1409 constexpr optional
1410 or_else(_Fn&& __f) const&
1411 {
1412 using _Up = invoke_result_t<_Fn>;
1413 static_assert(is_same_v<remove_cvref_t<_Up>, optional>,
1414 "the function passed to std::optional<T>::or_else "
1415 "must return a std::optional<T>");
1416
1417 if (has_value())
1418 return *this;
1419 else
1420 return std::forward<_Fn>(__f)();
1421 }
1422
1423 template<typename _Fn> requires invocable<_Fn> && move_constructible<_Tp>
1424 constexpr optional
1425 or_else(_Fn&& __f) &&
1426 {
1427 using _Up = invoke_result_t<_Fn>;
1428 static_assert(is_same_v<remove_cvref_t<_Up>, optional>,
1429 "the function passed to std::optional<T>::or_else "
1430 "must return a std::optional<T>");
1431
1432 if (has_value())
1433 return std::move(*this);
1434 else
1435 return std::forward<_Fn>(__f)();
1436 }
1437#endif
1438
1439 _GLIBCXX20_CONSTEXPR void reset() noexcept { this->_M_reset(); }
1440
1441 private:
1442 using _Base::_M_get;
1443
1444 template<typename _Up> friend class optional;
1445
1446#if __cpp_lib_optional >= 202110L // C++23
1447 template<typename _Fn, typename _Value>
1448 explicit constexpr
1449 optional(_Optional_func<_Fn> __f, _Value&& __v)
1450 {
1451 this->_M_payload._M_apply(__f, std::forward<_Value>(__v));
1452 }
1453#endif
1454 };
1455
1456 template<typename _Tp>
1457 using __optional_relop_t =
1458 enable_if_t<is_convertible_v<_Tp, bool>, bool>;
1459
1460 template<typename _Tp, typename _Up>
1461 using __optional_eq_t = __optional_relop_t<
1462 decltype(std::declval<const _Tp&>() == std::declval<const _Up&>())
1463 >;
1464
1465 template<typename _Tp, typename _Up>
1466 using __optional_ne_t = __optional_relop_t<
1467 decltype(std::declval<const _Tp&>() != std::declval<const _Up&>())
1468 >;
1469
1470 template<typename _Tp, typename _Up>
1471 using __optional_lt_t = __optional_relop_t<
1472 decltype(std::declval<const _Tp&>() < std::declval<const _Up&>())
1473 >;
1474
1475 template<typename _Tp, typename _Up>
1476 using __optional_gt_t = __optional_relop_t<
1477 decltype(std::declval<const _Tp&>() > std::declval<const _Up&>())
1478 >;
1479
1480 template<typename _Tp, typename _Up>
1481 using __optional_le_t = __optional_relop_t<
1482 decltype(std::declval<const _Tp&>() <= std::declval<const _Up&>())
1483 >;
1484
1485 template<typename _Tp, typename _Up>
1486 using __optional_ge_t = __optional_relop_t<
1487 decltype(std::declval<const _Tp&>() >= std::declval<const _Up&>())
1488 >;
1489
1490 // Comparisons between optional values.
1491 template<typename _Tp, typename _Up>
1492 constexpr auto
1493 operator==(const optional<_Tp>& __lhs, const optional<_Up>& __rhs)
1494 -> __optional_eq_t<_Tp, _Up>
1495 {
1496 return static_cast<bool>(__lhs) == static_cast<bool>(__rhs)
1497 && (!__lhs || *__lhs == *__rhs);
1498 }
1499
1500 template<typename _Tp, typename _Up>
1501 constexpr auto
1502 operator!=(const optional<_Tp>& __lhs, const optional<_Up>& __rhs)
1503 -> __optional_ne_t<_Tp, _Up>
1504 {
1505 return static_cast<bool>(__lhs) != static_cast<bool>(__rhs)
1506 || (static_cast<bool>(__lhs) && *__lhs != *__rhs);
1507 }
1508
1509 template<typename _Tp, typename _Up>
1510 constexpr auto
1511 operator<(const optional<_Tp>& __lhs, const optional<_Up>& __rhs)
1512 -> __optional_lt_t<_Tp, _Up>
1513 {
1514 return static_cast<bool>(__rhs) && (!__lhs || *__lhs < *__rhs);
1515 }
1516
1517 template<typename _Tp, typename _Up>
1518 constexpr auto
1519 operator>(const optional<_Tp>& __lhs, const optional<_Up>& __rhs)
1520 -> __optional_gt_t<_Tp, _Up>
1521 {
1522 return static_cast<bool>(__lhs) && (!__rhs || *__lhs > *__rhs);
1523 }
1524
1525 template<typename _Tp, typename _Up>
1526 constexpr auto
1527 operator<=(const optional<_Tp>& __lhs, const optional<_Up>& __rhs)
1528 -> __optional_le_t<_Tp, _Up>
1529 {
1530 return !__lhs || (static_cast<bool>(__rhs) && *__lhs <= *__rhs);
1531 }
1532
1533 template<typename _Tp, typename _Up>
1534 constexpr auto
1535 operator>=(const optional<_Tp>& __lhs, const optional<_Up>& __rhs)
1536 -> __optional_ge_t<_Tp, _Up>
1537 {
1538 return !__rhs || (static_cast<bool>(__lhs) && *__lhs >= *__rhs);
1539 }
1540
1541#ifdef __cpp_lib_three_way_comparison
1542 template<typename _Tp, three_way_comparable_with<_Tp> _Up>
1543 [[nodiscard]]
1544 constexpr compare_three_way_result_t<_Tp, _Up>
1545 operator<=>(const optional<_Tp>& __x, const optional<_Up>& __y)
1546 {
1547 return __x && __y ? *__x <=> *__y : bool(__x) <=> bool(__y);
1548 }
1549#endif
1550
1551 // Comparisons with nullopt.
1552 template<typename _Tp>
1553 [[nodiscard]]
1554 constexpr bool
1555 operator==(const optional<_Tp>& __lhs, nullopt_t) noexcept
1556 { return !__lhs; }
1557
1558#ifdef __cpp_lib_three_way_comparison
1559 template<typename _Tp>
1560 [[nodiscard]]
1561 constexpr strong_ordering
1562 operator<=>(const optional<_Tp>& __x, nullopt_t) noexcept
1563 { return bool(__x) <=> false; }
1564#else
1565 template<typename _Tp>
1566 constexpr bool
1567 operator==(nullopt_t, const optional<_Tp>& __rhs) noexcept
1568 { return !__rhs; }
1569
1570 template<typename _Tp>
1571 constexpr bool
1572 operator!=(const optional<_Tp>& __lhs, nullopt_t) noexcept
1573 { return static_cast<bool>(__lhs); }
1574
1575 template<typename _Tp>
1576 constexpr bool
1577 operator!=(nullopt_t, const optional<_Tp>& __rhs) noexcept
1578 { return static_cast<bool>(__rhs); }
1579
1580 template<typename _Tp>
1581 constexpr bool
1582 operator<(const optional<_Tp>& /* __lhs */, nullopt_t) noexcept
1583 { return false; }
1584
1585 template<typename _Tp>
1586 constexpr bool
1587 operator<(nullopt_t, const optional<_Tp>& __rhs) noexcept
1588 { return static_cast<bool>(__rhs); }
1589
1590 template<typename _Tp>
1591 constexpr bool
1592 operator>(const optional<_Tp>& __lhs, nullopt_t) noexcept
1593 { return static_cast<bool>(__lhs); }
1594
1595 template<typename _Tp>
1596 constexpr bool
1597 operator>(nullopt_t, const optional<_Tp>& /* __rhs */) noexcept
1598 { return false; }
1599
1600 template<typename _Tp>
1601 constexpr bool
1602 operator<=(const optional<_Tp>& __lhs, nullopt_t) noexcept
1603 { return !__lhs; }
1604
1605 template<typename _Tp>
1606 constexpr bool
1607 operator<=(nullopt_t, const optional<_Tp>& /* __rhs */) noexcept
1608 { return true; }
1609
1610 template<typename _Tp>
1611 constexpr bool
1612 operator>=(const optional<_Tp>& /* __lhs */, nullopt_t) noexcept
1613 { return true; }
1614
1615 template<typename _Tp>
1616 constexpr bool
1617 operator>=(nullopt_t, const optional<_Tp>& __rhs) noexcept
1618 { return !__rhs; }
1619#endif // three-way-comparison
1620
1621#if __cpp_lib_concepts
1622 // _GLIBCXX_RESOLVE_LIB_DEFECTS
1623 // 4072. std::optional comparisons: constrain harder
1624# define _REQUIRES_NOT_OPTIONAL(T) requires (!__is_optional_v<T>)
1625#else
1626# define _REQUIRES_NOT_OPTIONAL(T)
1627#endif
1628
1629 // Comparisons with value type.
1630 template<typename _Tp, typename _Up>
1631 _REQUIRES_NOT_OPTIONAL(_Up)
1632 constexpr auto
1633 operator== [[nodiscard]] (const optional<_Tp>& __lhs, const _Up& __rhs)
1634 -> __optional_eq_t<_Tp, _Up>
1635 { return __lhs && *__lhs == __rhs; }
1636
1637 template<typename _Tp, typename _Up>
1638 _REQUIRES_NOT_OPTIONAL(_Tp)
1639 constexpr auto
1640 operator== [[nodiscard]] (const _Tp& __lhs, const optional<_Up>& __rhs)
1641 -> __optional_eq_t<_Tp, _Up>
1642 { return __rhs && __lhs == *__rhs; }
1643
1644 template<typename _Tp, typename _Up>
1645 _REQUIRES_NOT_OPTIONAL(_Up)
1646 constexpr auto
1647 operator!= [[nodiscard]] (const optional<_Tp>& __lhs, const _Up& __rhs)
1648 -> __optional_ne_t<_Tp, _Up>
1649 { return !__lhs || *__lhs != __rhs; }
1650
1651 template<typename _Tp, typename _Up>
1652 _REQUIRES_NOT_OPTIONAL(_Tp)
1653 constexpr auto
1654 operator!= [[nodiscard]] (const _Tp& __lhs, const optional<_Up>& __rhs)
1655 -> __optional_ne_t<_Tp, _Up>
1656 { return !__rhs || __lhs != *__rhs; }
1657
1658 template<typename _Tp, typename _Up>
1659 _REQUIRES_NOT_OPTIONAL(_Up)
1660 constexpr auto
1661 operator< [[nodiscard]] (const optional<_Tp>& __lhs, const _Up& __rhs)
1662 -> __optional_lt_t<_Tp, _Up>
1663 { return !__lhs || *__lhs < __rhs; }
1664
1665 template<typename _Tp, typename _Up>
1666 _REQUIRES_NOT_OPTIONAL(_Tp)
1667 constexpr auto
1668 operator< [[nodiscard]] (const _Tp& __lhs, const optional<_Up>& __rhs)
1669 -> __optional_lt_t<_Tp, _Up>
1670 { return __rhs && __lhs < *__rhs; }
1671
1672 template<typename _Tp, typename _Up>
1673 _REQUIRES_NOT_OPTIONAL(_Up)
1674 constexpr auto
1675 operator> [[nodiscard]] (const optional<_Tp>& __lhs, const _Up& __rhs)
1676 -> __optional_gt_t<_Tp, _Up>
1677 { return __lhs && *__lhs > __rhs; }
1678
1679 template<typename _Tp, typename _Up>
1680 _REQUIRES_NOT_OPTIONAL(_Tp)
1681 constexpr auto
1682 operator> [[nodiscard]] (const _Tp& __lhs, const optional<_Up>& __rhs)
1683 -> __optional_gt_t<_Tp, _Up>
1684 { return !__rhs || __lhs > *__rhs; }
1685
1686 template<typename _Tp, typename _Up>
1687 _REQUIRES_NOT_OPTIONAL(_Up)
1688 constexpr auto
1689 operator<= [[nodiscard]] (const optional<_Tp>& __lhs, const _Up& __rhs)
1690 -> __optional_le_t<_Tp, _Up>
1691 { return !__lhs || *__lhs <= __rhs; }
1692
1693 template<typename _Tp, typename _Up>
1694 _REQUIRES_NOT_OPTIONAL(_Tp)
1695 constexpr auto
1696 operator<= [[nodiscard]] (const _Tp& __lhs, const optional<_Up>& __rhs)
1697 -> __optional_le_t<_Tp, _Up>
1698 { return __rhs && __lhs <= *__rhs; }
1699
1700 template<typename _Tp, typename _Up>
1701 _REQUIRES_NOT_OPTIONAL(_Up)
1702 constexpr auto
1703 operator>= [[nodiscard]] (const optional<_Tp>& __lhs, const _Up& __rhs)
1704 -> __optional_ge_t<_Tp, _Up>
1705 { return __lhs && *__lhs >= __rhs; }
1706
1707 template<typename _Tp, typename _Up>
1708 _REQUIRES_NOT_OPTIONAL(_Tp)
1709 constexpr auto
1710 operator>= [[nodiscard]] (const _Tp& __lhs, const optional<_Up>& __rhs)
1711 -> __optional_ge_t<_Tp, _Up>
1712 { return !__rhs || __lhs >= *__rhs; }
1713
1714#ifdef __cpp_lib_three_way_comparison
1715 // _GLIBCXX_RESOLVE_LIB_DEFECTS
1716 // 3746. optional's spaceship with U with a type derived from optional
1717 // causes infinite constraint meta-recursion
1718 template<typename _Tp>
1719 concept __is_derived_from_optional = requires (const _Tp& __t) {
1720 []<typename _Up>(const optional<_Up>&){ }(__t);
1721 };
1722
1723 template<typename _Tp, typename _Up>
1724 requires (!__is_derived_from_optional<_Up>)
1725 && requires { typename compare_three_way_result_t<_Tp, _Up>; }
1726 && three_way_comparable_with<_Tp, _Up>
1727 constexpr compare_three_way_result_t<_Tp, _Up>
1728 operator<=> [[nodiscard]] (const optional<_Tp>& __x, const _Up& __v)
1729 { return bool(__x) ? *__x <=> __v : strong_ordering::less; }
1730#endif
1731
1732 // Swap and creation functions.
1733
1734 // _GLIBCXX_RESOLVE_LIB_DEFECTS
1735 // 2748. swappable traits for optionals
1736 template<typename _Tp>
1737 _GLIBCXX20_CONSTEXPR
1738 inline enable_if_t<is_move_constructible_v<_Tp> && is_swappable_v<_Tp>>
1739 swap(optional<_Tp>& __lhs, optional<_Tp>& __rhs)
1740 noexcept(noexcept(__lhs.swap(__rhs)))
1741 { __lhs.swap(__rhs); }
1742
1743 // _GLIBCXX_RESOLVE_LIB_DEFECTS
1744 // 2766. Swapping non-swappable types
1745 template<typename _Tp>
1746 enable_if_t<!(is_move_constructible_v<_Tp> && is_swappable_v<_Tp>)>
1747 swap(optional<_Tp>&, optional<_Tp>&) = delete;
1748
1749 template<typename _Tp>
1750 constexpr
1751 enable_if_t<is_constructible_v<decay_t<_Tp>, _Tp>,
1752 optional<decay_t<_Tp>>>
1753 make_optional(_Tp&& __t)
1754 noexcept(is_nothrow_constructible_v<optional<decay_t<_Tp>>, _Tp>)
1755 { return optional<decay_t<_Tp>>{ std::forward<_Tp>(__t) }; }
1756
1757 template<typename _Tp, typename... _Args>
1758 constexpr
1759 enable_if_t<is_constructible_v<_Tp, _Args...>,
1760 optional<_Tp>>
1761 make_optional(_Args&&... __args)
1762 noexcept(is_nothrow_constructible_v<_Tp, _Args...>)
1763 { return optional<_Tp>{ in_place, std::forward<_Args>(__args)... }; }
1764
1765 template<typename _Tp, typename _Up, typename... _Args>
1766 constexpr
1767 enable_if_t<is_constructible_v<_Tp, initializer_list<_Up>&, _Args...>,
1768 optional<_Tp>>
1769 make_optional(initializer_list<_Up> __il, _Args&&... __args)
1770 noexcept(is_nothrow_constructible_v<_Tp, initializer_list<_Up>&, _Args...>)
1771 { return optional<_Tp>{ in_place, __il, std::forward<_Args>(__args)... }; }
1772
1773 // Hash.
1774
1775 template<typename _Tp, typename _Up = remove_const_t<_Tp>>
1776 struct __optional_hash
1777#if ! _GLIBCXX_INLINE_VERSION
1778 : public __hash_empty_base<_Up>
1779#endif
1780 {
1781#if __cplusplus < 202002L
1782 using result_type [[__deprecated__]] = size_t;
1783 using argument_type [[__deprecated__]] = optional<_Tp>;
1784#endif
1785
1786 size_t
1787 operator()(const optional<_Tp>& __t) const
1788 noexcept(noexcept(hash<_Up>{}(*__t)))
1789 {
1790 // We pick an arbitrary hash for disengaged optionals which hopefully
1791 // usual values of _Tp won't typically hash to.
1792 constexpr size_t __magic_disengaged_hash = static_cast<size_t>(-3333);
1793 return __t ? hash<_Up>{}(*__t) : __magic_disengaged_hash;
1794 }
1795 };
1796
1797 template<typename _Tp>
1798 struct hash<optional<_Tp>>
1799 : public __conditional_t<__is_hash_enabled_for<remove_const_t<_Tp>>,
1800 __optional_hash<_Tp>,
1801 __hash_not_enabled<_Tp>>
1802 { };
1803
1804 template<typename _Tp>
1805 struct __is_fast_hash<hash<optional<_Tp>>> : __is_fast_hash<hash<_Tp>>
1806 { };
1807
1808 /// @}
1809
1810#if __cpp_deduction_guides >= 201606
1811 template <typename _Tp> optional(_Tp) -> optional<_Tp>;
1812#endif
1813
1814#ifdef __cpp_lib_optional_range_support // >= C++26
1815 template<typename _Tp>
1816 inline constexpr bool
1817 ranges::enable_view<optional<_Tp>> = true;
1818
1819 template<typename _Tp>
1820 inline constexpr range_format
1821 format_kind<optional<_Tp>> = range_format::disabled;
1822#endif // __cpp_lib_optional_range_support
1823
1824#undef _GLIBCXX_USE_CONSTRAINTS_FOR_OPTIONAL
1825
1826_GLIBCXX_END_NAMESPACE_VERSION
1827} // namespace std
1828
1829#endif // __cpp_lib_optional
1830
1831#endif // _GLIBCXX_OPTIONAL