1// <optional> -*- C++ -*-
3// Copyright (C) 2013-2025 Free Software Foundation, Inc.
4// Copyright The GNU Toolchain Authors.
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)
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.
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.
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/>.
26/** @file include/optional
27 * This is a Standard C++ Library header.
30#ifndef _GLIBCXX_OPTIONAL
31#define _GLIBCXX_OPTIONAL 1
34#pragma GCC system_header
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>
43#ifdef __cpp_lib_optional // C++ >= 17
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
56# include <bits/invoke.h> // std::__invoke
58#if __cplusplus > 202002L
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>
67namespace std _GLIBCXX_VISIBILITY(default)
69_GLIBCXX_BEGIN_NAMESPACE_VERSION
72 * @addtogroup utilities
76 template<typename _Tp>
79 /// Tag type to disengage optional objects.
82 // Do not user-declare default constructor at all for
83 // optional_value = {} syntax to work.
84 // nullopt_t() = delete;
86 // Used for constructing nullopt.
87 enum class _Construct { _Token };
89 // Must be constexpr for nullopt_t to be literal.
90 explicit constexpr nullopt_t(_Construct) noexcept { }
93 /// Tag to disengage optional objects.
94 inline constexpr nullopt_t nullopt { nullopt_t::_Construct::_Token };
96 template<typename _Fn> struct _Optional_func { _Fn& _M_f; };
99 * @brief Exception class thrown when a disengaged optional object is
101 * @ingroup exceptions
103 class bad_optional_access : public exception
106 bad_optional_access() = default;
107 virtual ~bad_optional_access() = default;
109 const char* what() const noexcept override
110 { return "bad optional access"; }
113 // XXX Does not belong here.
114 [[__noreturn__]] inline void
115 __throw_bad_optional_access()
116 { _GLIBCXX_THROW_OR_ABORT(bad_optional_access()); }
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
123 using _Stored_type = remove_const_t<_Tp>;
125 _Optional_payload_base() = default;
126 ~_Optional_payload_base() = default;
128 template<typename... _Args>
130 _Optional_payload_base(in_place_t __tag, _Args&&... __args)
131 : _M_payload(__tag, std::forward<_Args>(__args)...),
135 template<typename _Up, typename... _Args>
137 _Optional_payload_base(std::initializer_list<_Up> __il,
139 : _M_payload(__il, std::forward<_Args>(__args)...),
143 // Constructor used by _Optional_base copy constructor when the
144 // contained value is not trivially copy constructible.
146 _Optional_payload_base(bool /* __engaged */,
147 const _Optional_payload_base& __other)
149 if (__other._M_engaged)
150 this->_M_construct(__other._M_get());
153 // Constructor used by _Optional_base move constructor when the
154 // contained value is not trivially move constructible.
156 _Optional_payload_base(bool /* __engaged */,
157 _Optional_payload_base&& __other)
159 if (__other._M_engaged)
160 this->_M_construct(std::move(__other._M_get()));
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;
167 // Move constructor is only used to when the contained value is
168 // trivially copy constructible.
169 _Optional_payload_base(_Optional_payload_base&&) = default;
171 _Optional_payload_base&
172 operator=(const _Optional_payload_base&) = default;
174 _Optional_payload_base&
175 operator=(_Optional_payload_base&&) = default;
177 // used to perform non-trivial copy assignment.
179 _M_copy_assign(const _Optional_payload_base& __other)
181 if (this->_M_engaged && __other._M_engaged)
182 this->_M_get() = __other._M_get();
185 if (__other._M_engaged)
186 this->_M_construct(__other._M_get());
192 // used to perform non-trivial move assignment.
194 _M_move_assign(_Optional_payload_base&& __other)
195 noexcept(__and_v<is_nothrow_move_constructible<_Tp>,
196 is_nothrow_move_assignable<_Tp>>)
198 if (this->_M_engaged && __other._M_engaged)
199 this->_M_get() = std::move(__other._M_get());
202 if (__other._M_engaged)
203 this->_M_construct(std::move(__other._M_get()));
209 struct _Empty_byte { };
211 template<typename _Up, bool = is_trivially_destructible_v<_Up>>
214 constexpr _Storage() noexcept : _M_empty() { }
216 template<typename... _Args>
218 _Storage(in_place_t, _Args&&... __args)
219 : _M_value(std::forward<_Args>(__args)...)
222 template<typename _Vp, typename... _Args>
224 _Storage(std::initializer_list<_Vp> __il, _Args&&... __args)
225 : _M_value(__il, std::forward<_Args>(__args)...)
228#if __cplusplus >= 202002L
229 template<typename _Fn, typename _Arg>
231 _Storage(_Optional_func<_Fn> __f, _Arg&& __arg)
232 : _M_value(std::__invoke(std::forward<_Fn>(__f._M_f),
233 std::forward<_Arg>(__arg)))
237#if __cpp_concepts >= 202002L // Conditionally trivial special member functions
238 ~_Storage() = default;
240 // User-provided destructor is needed when _Up has non-trivial dtor.
242 ~_Storage() requires (!is_trivially_destructible_v<_Up>)
245 _Storage(const _Storage&) = default;
246 _Storage(_Storage&&) = default;
247 _Storage& operator=(const _Storage&) = default;
248 _Storage& operator=(_Storage&&) = default;
251 _Empty_byte _M_empty;
255#if __cpp_concepts < 202002L
256 template<typename _Up>
257 union _Storage<_Up, false>
259 constexpr _Storage() noexcept : _M_empty() { }
261 template<typename... _Args>
263 _Storage(in_place_t, _Args&&... __args)
264 : _M_value(std::forward<_Args>(__args)...)
267 template<typename _Vp, typename... _Args>
269 _Storage(std::initializer_list<_Vp> __il, _Args&&... __args)
270 : _M_value(__il, std::forward<_Args>(__args)...)
273#if __cplusplus >= 202002L
274 template<typename _Fn, typename _Arg>
276 _Storage(_Optional_func<_Fn> __f, _Arg&& __arg)
277 : _M_value(std::__invoke(std::forward<_Fn>(__f._M_f),
278 std::forward<_Arg>(__arg)))
282 // User-provided destructor is needed when _Up has non-trivial dtor.
283 _GLIBCXX20_CONSTEXPR ~_Storage() { }
285 _Storage(const _Storage&) = default;
286 _Storage(_Storage&&) = default;
287 _Storage& operator=(const _Storage&) = default;
288 _Storage& operator=(_Storage&&) = default;
290 _Empty_byte _M_empty;
295 _Storage<_Stored_type> _M_payload;
297 bool _M_engaged = false;
299 template<typename... _Args>
301 _M_construct(_Args&&... __args)
302 noexcept(is_nothrow_constructible_v<_Stored_type, _Args...>)
304 std::_Construct(std::__addressof(this->_M_payload._M_value),
305 std::forward<_Args>(__args)...);
306 this->_M_engaged = true;
310 _M_destroy() noexcept
313 _M_payload._M_value.~_Stored_type();
316#if __cplusplus >= 202002L
317 template<typename _Fn, typename _Up>
319 _M_apply(_Optional_func<_Fn> __f, _Up&& __x)
321 std::construct_at(std::__addressof(this->_M_payload),
322 __f, std::forward<_Up>(__x));
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.
333 { return this->_M_payload._M_value; }
336 _M_get() const noexcept
337 { return this->_M_payload._M_value; }
339 // _M_reset is a 'safe' operation with no precondition.
343 if (this->_M_engaged)
345 else // This seems redundant but improves codegen, see PR 112480.
346 this->_M_engaged = false;
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;
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>
367 using _Optional_payload_base<_Tp>::_Optional_payload_base;
369 _Optional_payload() = default;
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>
377 using _Optional_payload_base<_Tp>::_Optional_payload_base;
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;
385 // Non-trivial copy assignment.
388 operator=(const _Optional_payload& __other)
390 this->_M_copy_assign(__other);
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>
400 using _Optional_payload_base<_Tp>::_Optional_payload_base;
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;
408 // Non-trivial move assignment.
411 operator=(_Optional_payload&& __other)
412 noexcept(__and_v<is_nothrow_move_constructible<_Tp>,
413 is_nothrow_move_assignable<_Tp>>)
415 this->_M_move_assign(std::move(__other));
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>
425 using _Optional_payload_base<_Tp>::_Optional_payload_base;
427 _Optional_payload() = default;
428 ~_Optional_payload() = default;
429 _Optional_payload(const _Optional_payload&) = default;
430 _Optional_payload(_Optional_payload&&) = default;
432 // Non-trivial copy assignment.
435 operator=(const _Optional_payload& __other)
437 this->_M_copy_assign(__other);
441 // Non-trivial move assignment.
444 operator=(_Optional_payload&& __other)
445 noexcept(__and_v<is_nothrow_move_constructible<_Tp>,
446 is_nothrow_move_assignable<_Tp>>)
448 this->_M_move_assign(std::move(__other));
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>
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;
466 // Destructor needs to destroy the contained value:
467 _GLIBCXX20_CONSTEXPR ~_Optional_payload() { this->_M_reset(); }
471 * @brief Class template that provides copy/move constructors of optional.
473 * Such a separate base class template is necessary in order to
474 * conditionally make copy/move constructors trivial.
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.
483 * Whether the other special members are trivial is determined by the
484 * _Optional_payload<_Tp> specialization used for the _M_payload member.
486 * @see optional, _Enable_special_members
488 template<typename _Tp,
489 bool = is_trivially_copy_constructible_v<_Tp>,
490 bool = is_trivially_move_constructible_v<_Tp>>
491 struct _Optional_base
493 // Constructors for disengaged optionals.
494 constexpr _Optional_base() = default;
496 // Constructors for engaged optionals.
497 template<typename... _Args,
498 enable_if_t<is_constructible_v<_Tp, _Args...>, bool> = false>
500 _Optional_base(in_place_t, _Args&&... __args)
501 : _M_payload(in_place, std::forward<_Args>(__args)...)
504 template<typename _Up, typename... _Args,
505 enable_if_t<is_constructible_v<_Tp,
506 initializer_list<_Up>&,
507 _Args...>, bool> = false>
509 _Optional_base(in_place_t,
510 initializer_list<_Up> __il,
512 : _M_payload(in_place, __il, std::forward<_Args>(__args)...)
515 // Copy and move constructors.
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)
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))
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;
535 constexpr _Optional_base(_Optional_base&&)
536 requires is_trivially_move_constructible_v<_Tp> = default;
539 // Assignment operators.
540 _Optional_base& operator=(const _Optional_base&) = default;
541 _Optional_base& operator=(_Optional_base&&) = default;
543 _Optional_payload<_Tp> _M_payload;
546 // For the primary template, we define these functions here.
547 using _Stored_type = remove_const_t<_Tp>;
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>
553 _M_construct(_Args&&... __args)
554 noexcept(is_nothrow_constructible_v<_Stored_type, _Args...>)
556 _M_payload._M_construct(std::forward<_Args>(__args)...);
560 _M_destruct() noexcept
561 { _M_payload._M_destroy(); }
563 // _M_reset is a 'safe' operation with no precondition.
566 { _M_payload._M_reset(); }
568 constexpr bool _M_is_engaged() const noexcept
569 { return _M_payload._M_engaged; }
571 // The _M_get operations have _M_engaged as a precondition.
574 { return _M_payload._M_get(); }
577 _M_get() const noexcept
578 { return _M_payload._M_get(); }
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.
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
596 using _Stored_type = remove_const_t<_Tp>;
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>
602 _M_construct(_Args&&... __args)
603 noexcept(is_nothrow_constructible_v<_Stored_type, _Args...>)
605 static_cast<_Dp*>(this)->_M_payload._M_construct(
606 std::forward<_Args>(__args)...);
610 _M_destruct() noexcept
611 { static_cast<_Dp*>(this)->_M_payload._M_destroy(); }
613 // _M_reset is a 'safe' operation with no precondition.
616 { static_cast<_Dp*>(this)->_M_payload._M_reset(); }
618 constexpr bool _M_is_engaged() const noexcept
619 { return static_cast<const _Dp*>(this)->_M_payload._M_engaged; }
621 // The _M_get operations have _M_engaged as a precondition.
624 { return static_cast<_Dp*>(this)->_M_payload._M_get(); }
627 _M_get() const noexcept
628 { return static_cast<const _Dp*>(this)->_M_payload._M_get(); }
631 template<typename _Tp>
632 struct _Optional_base<_Tp, false, true> // trivial move ctor
633 : _Optional_base_impl<_Tp, _Optional_base<_Tp>>
635 // Constructors for disengaged optionals.
636 constexpr _Optional_base() = default;
638 // Constructors for engaged optionals.
639 template<typename... _Args,
640 enable_if_t<is_constructible_v<_Tp, _Args...>, bool> = false>
642 _Optional_base(in_place_t, _Args&&... __args)
643 : _M_payload(in_place, std::forward<_Args>(__args)...)
646 template<typename _Up, typename... _Args,
647 enable_if_t<is_constructible_v<_Tp,
648 initializer_list<_Up>&,
649 _Args...>, bool> = false>
651 _Optional_base(in_place_t,
652 initializer_list<_Up> __il,
654 : _M_payload(in_place, __il, std::forward<_Args>(__args)...)
657 // Copy and move constructors.
658 constexpr _Optional_base(const _Optional_base& __other)
659 : _M_payload(__other._M_payload._M_engaged, __other._M_payload)
662 constexpr _Optional_base(_Optional_base&& __other) = default;
664 // Assignment operators.
665 _Optional_base& operator=(const _Optional_base&) = default;
666 _Optional_base& operator=(_Optional_base&&) = default;
668 _Optional_payload<_Tp> _M_payload;
671 template<typename _Tp>
672 struct _Optional_base<_Tp, true, false> // trivial copy ctor
673 : _Optional_base_impl<_Tp, _Optional_base<_Tp>>
675 // Constructors for disengaged optionals.
676 constexpr _Optional_base() = default;
678 // Constructors for engaged optionals.
679 template<typename... _Args,
680 enable_if_t<is_constructible_v<_Tp, _Args...>, bool> = false>
682 _Optional_base(in_place_t, _Args&&... __args)
683 : _M_payload(in_place, std::forward<_Args>(__args)...)
686 template<typename _Up, typename... _Args,
687 enable_if_t<is_constructible_v<_Tp,
688 initializer_list<_Up>&,
689 _Args...>, bool> = false>
691 _Optional_base(in_place_t,
692 initializer_list<_Up> __il,
694 : _M_payload(in_place, __il, std::forward<_Args>(__args)...)
697 // Copy and move constructors.
698 constexpr _Optional_base(const _Optional_base& __other) = default;
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))
707 // Assignment operators.
708 _Optional_base& operator=(const _Optional_base&) = default;
709 _Optional_base& operator=(_Optional_base&&) = default;
711 _Optional_payload<_Tp> _M_payload;
714 template<typename _Tp>
715 struct _Optional_base<_Tp, true, true> // trivial copy and move ctors
716 : _Optional_base_impl<_Tp, _Optional_base<_Tp>>
718 // Constructors for disengaged optionals.
719 constexpr _Optional_base() = default;
721 // Constructors for engaged optionals.
722 template<typename... _Args,
723 enable_if_t<is_constructible_v<_Tp, _Args...>, bool> = false>
725 _Optional_base(in_place_t, _Args&&... __args)
726 : _M_payload(in_place, std::forward<_Args>(__args)...)
729 template<typename _Up, typename... _Args,
730 enable_if_t<is_constructible_v<_Tp,
731 initializer_list<_Up>&,
732 _Args...>, bool> = false>
734 _Optional_base(in_place_t,
735 initializer_list<_Up> __il,
737 : _M_payload(in_place, __il, std::forward<_Args>(__args)...)
740 // Copy and move constructors.
741 constexpr _Optional_base(const _Optional_base& __other) = default;
742 constexpr _Optional_base(_Optional_base&& __other) = default;
744 // Assignment operators.
745 _Optional_base& operator=(const _Optional_base&) = default;
746 _Optional_base& operator=(_Optional_base&&) = default;
748 _Optional_payload<_Tp> _M_payload;
750#endif // __cpp_concepts
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;
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>
765 template<typename _Tp, typename _Up>
766 using __converts_from_optional
767 = __converts_from_any_cvref<_Tp, optional<_Up>>;
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>&&>>;
776#if __cpp_concepts && __cpp_conditional_explicit && __glibcxx_remove_cvref
777# define _GLIBCXX_USE_CONSTRAINTS_FOR_OPTIONAL 1
781 * @brief Class template for optional values.
783 template<typename _Tp>
785 : private _Optional_base<_Tp>,
786 private _Enable_copy_move<
788 is_copy_constructible_v<_Tp>,
790 __and_v<is_copy_constructible<_Tp>, is_copy_assignable<_Tp>>,
792 is_move_constructible_v<_Tp>,
794 __and_v<is_move_constructible<_Tp>, is_move_assignable<_Tp>>,
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>);
803 using _Base = _Optional_base<_Tp>;
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
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>>;
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;
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>
837 template<typename _From, typename = remove_cv_t<_Tp>>
838 struct __not_constructing_bool_from_optional
842 template<typename _From>
843 struct __not_constructing_bool_from_optional<_From, bool>
844 : bool_constant<!__is_optional_v<__remove_cvref_t<_From>>>
847 template<typename _From, typename = remove_cv_t<_Tp>>
848 struct __construct_from_contained_value
849 : __not_<__converts_from_optional<_Tp, _From>>
852 template<typename _From>
853 struct __construct_from_contained_value<_From, bool>
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>;
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>;
872 constexpr optional() noexcept { }
874 constexpr optional(nullopt_t) noexcept { }
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>)
885 noexcept(is_nothrow_constructible_v<_Tp, _Up>)
886 : _Base(std::in_place, std::forward<_Up>(__t)) { }
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&>)
897 emplace(__t._M_get());
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>)
909 emplace(std::move(__t._M_get()));
912 template<typename... _Args>
913 requires is_constructible_v<_Tp, _Args...>
915 optional(in_place_t, _Args&&... __args)
916 noexcept(is_nothrow_constructible_v<_Tp, _Args...>)
917 : _Base(std::in_place, std::forward<_Args>(__args)...)
920 template<typename _Up, typename... _Args>
921 requires is_constructible_v<_Tp, initializer_list<_Up>&, _Args...>
923 optional(in_place_t, initializer_list<_Up> __il, _Args&&... __args)
924 noexcept(is_nothrow_constructible_v<_Tp, initializer_list<_Up>&,
926 : _Base(std::in_place, __il, std::forward<_Args>(__args)...)
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>
936 noexcept(is_nothrow_constructible_v<_Tp, _Up>)
937 : _Base(std::in_place, std::forward<_Up>(__t)) { }
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>
946 noexcept(is_nothrow_constructible_v<_Tp, _Up>)
947 : _Base(std::in_place, std::forward<_Up>(__t)) { }
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>
955 optional(const optional<_Up>& __t)
956 noexcept(is_nothrow_constructible_v<_Tp, const _Up&>)
959 emplace(__t._M_get());
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>
968 optional(const optional<_Up>& __t)
969 noexcept(is_nothrow_constructible_v<_Tp, const _Up&>)
972 emplace(__t._M_get());
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>
981 optional(optional<_Up>&& __t)
982 noexcept(is_nothrow_constructible_v<_Tp, _Up>)
985 emplace(std::move(__t._M_get()));
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>
994 optional(optional<_Up>&& __t)
995 noexcept(is_nothrow_constructible_v<_Tp, _Up>)
998 emplace(std::move(__t._M_get()));
1001 template<typename... _Args,
1002 _Requires<is_constructible<_Tp, _Args...>> = false>
1004 optional(in_place_t, _Args&&... __args)
1005 noexcept(is_nothrow_constructible_v<_Tp, _Args...>)
1006 : _Base(std::in_place, std::forward<_Args>(__args)...) { }
1008 template<typename _Up, typename... _Args,
1009 _Requires<is_constructible<_Tp,
1010 initializer_list<_Up>&,
1013 optional(in_place_t, initializer_list<_Up> __il, _Args&&... __args)
1014 noexcept(is_nothrow_constructible_v<_Tp, initializer_list<_Up>&,
1016 : _Base(std::in_place, __il, std::forward<_Args>(__args)...) { }
1019 // Assignment operators.
1020 _GLIBCXX20_CONSTEXPR optional&
1021 operator=(nullopt_t) noexcept
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>
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>>,
1042 operator=(_Up&& __u)
1043 noexcept(__and_v<is_nothrow_constructible<_Tp, _Up>,
1044 is_nothrow_assignable<_Tp&, _Up>>)
1046 if (this->_M_is_engaged())
1047 this->_M_get() = std::forward<_Up>(__u);
1049 this->_M_construct(std::forward<_Up>(__u));
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)
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>>>,
1070 operator=(const optional<_Up>& __u)
1071 noexcept(__and_v<is_nothrow_constructible<_Tp, const _Up&>,
1072 is_nothrow_assignable<_Tp&, const _Up&>>)
1076 if (this->_M_is_engaged())
1077 this->_M_get() = __u._M_get();
1079 this->_M_construct(__u._M_get());
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)
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>>>,
1104 operator=(optional<_Up>&& __u)
1105 noexcept(__and_v<is_nothrow_constructible<_Tp, _Up>,
1106 is_nothrow_assignable<_Tp&, _Up>>)
1110 if (this->_M_is_engaged())
1111 this->_M_get() = std::move(__u._M_get());
1113 this->_M_construct(std::move(__u._M_get()));
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...>)
1130 this->_M_construct(std::forward<_Args>(__args)...);
1131 return this->_M_get();
1134 template<typename _Up, typename... _Args>
1135 _GLIBCXX20_CONSTEXPR
1136 enable_if_t<is_constructible_v<_Tp, initializer_list<_Up>&, _Args...>,
1138 emplace(initializer_list<_Up> __il, _Args&&... __args)
1139 noexcept(is_nothrow_constructible_v<_Tp, initializer_list<_Up>&,
1143 this->_M_construct(__il, std::forward<_Args>(__args)...);
1144 return this->_M_get();
1147 // Destructor is implicit, implemented in _Optional_base.
1150 _GLIBCXX20_CONSTEXPR void
1151 swap(optional& __other)
1152 noexcept(is_nothrow_move_constructible_v<_Tp>
1153 && is_nothrow_swappable_v<_Tp>)
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())
1161 __other._M_construct(std::move(this->_M_get()));
1162 this->_M_destruct();
1164 else if (__other._M_is_engaged())
1166 this->_M_construct(std::move(__other._M_get()));
1167 __other._M_destruct();
1171#ifdef __cpp_lib_optional_range_support // >= C++26
1172 // Iterator support.
1173 constexpr iterator begin() noexcept
1176 this->_M_is_engaged() ? std::addressof(this->_M_get()) : nullptr
1180 constexpr const_iterator begin() const noexcept
1182 return const_iterator(
1183 this->_M_is_engaged() ? std::addressof(this->_M_get()) : nullptr
1187 constexpr iterator end() noexcept
1189 return begin() + has_value();
1192 constexpr const_iterator end() const noexcept
1194 return begin() + has_value();
1196#endif // __cpp_lib_optional_range_support
1199 constexpr const _Tp*
1200 operator->() const noexcept
1202 __glibcxx_assert(this->_M_is_engaged());
1203 return std::__addressof(this->_M_get());
1207 operator->() noexcept
1209 __glibcxx_assert(this->_M_is_engaged());
1210 return std::__addressof(this->_M_get());
1213 constexpr const _Tp&
1214 operator*() const& noexcept
1216 __glibcxx_assert(this->_M_is_engaged());
1217 return this->_M_get();
1221 operator*()& noexcept
1223 __glibcxx_assert(this->_M_is_engaged());
1224 return this->_M_get();
1228 operator*()&& noexcept
1230 __glibcxx_assert(this->_M_is_engaged());
1231 return std::move(this->_M_get());
1234 constexpr const _Tp&&
1235 operator*() const&& noexcept
1237 __glibcxx_assert(this->_M_is_engaged());
1238 return std::move(this->_M_get());
1241 constexpr explicit operator bool() const noexcept
1242 { return this->_M_is_engaged(); }
1244 constexpr bool has_value() const noexcept
1245 { return this->_M_is_engaged(); }
1247 constexpr const _Tp&
1250 if (this->_M_is_engaged())
1251 return this->_M_get();
1252 __throw_bad_optional_access();
1258 if (this->_M_is_engaged())
1259 return this->_M_get();
1260 __throw_bad_optional_access();
1266 if (this->_M_is_engaged())
1267 return std::move(this->_M_get());
1268 __throw_bad_optional_access();
1271 constexpr const _Tp&&
1274 if (this->_M_is_engaged())
1275 return std::move(this->_M_get());
1276 __throw_bad_optional_access();
1279 template<typename _Up = remove_cv_t<_Tp>>
1281 value_or(_Up&& __u) const&
1283 static_assert(is_copy_constructible_v<_Tp>);
1284 static_assert(is_convertible_v<_Up&&, _Tp>);
1286 if (this->_M_is_engaged())
1287 return this->_M_get();
1289 return static_cast<_Tp>(std::forward<_Up>(__u));
1292 template<typename _Up = remove_cv_t<_Tp>>
1294 value_or(_Up&& __u) &&
1296 static_assert(is_move_constructible_v<_Tp>);
1297 static_assert(is_convertible_v<_Up&&, _Tp>);
1299 if (this->_M_is_engaged())
1300 return std::move(this->_M_get());
1302 return static_cast<_Tp>(std::forward<_Up>(__u));
1305#if __cpp_lib_optional >= 202110L // C++23
1306 // [optional.monadic]
1308 template<typename _Fn>
1310 and_then(_Fn&& __f) &
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");
1317 return std::__invoke(std::forward<_Fn>(__f), _M_get());
1322 template<typename _Fn>
1324 and_then(_Fn&& __f) const &
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");
1331 return std::__invoke(std::forward<_Fn>(__f), _M_get());
1336 template<typename _Fn>
1338 and_then(_Fn&& __f) &&
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");
1345 return std::__invoke(std::forward<_Fn>(__f), std::move(_M_get()));
1350 template<typename _Fn>
1352 and_then(_Fn&& __f) const &&
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");
1359 return std::__invoke(std::forward<_Fn>(__f), std::move(_M_get()));
1364 template<typename _Fn>
1366 transform(_Fn&& __f) &
1368 using _Up = remove_cv_t<invoke_result_t<_Fn, _Tp&>>;
1370 return optional<_Up>(_Optional_func<_Fn>{__f}, _M_get());
1372 return optional<_Up>();
1375 template<typename _Fn>
1377 transform(_Fn&& __f) const &
1379 using _Up = remove_cv_t<invoke_result_t<_Fn, const _Tp&>>;
1381 return optional<_Up>(_Optional_func<_Fn>{__f}, _M_get());
1383 return optional<_Up>();
1386 template<typename _Fn>
1388 transform(_Fn&& __f) &&
1390 using _Up = remove_cv_t<invoke_result_t<_Fn, _Tp>>;
1392 return optional<_Up>(_Optional_func<_Fn>{__f}, std::move(_M_get()));
1394 return optional<_Up>();
1397 template<typename _Fn>
1399 transform(_Fn&& __f) const &&
1401 using _Up = remove_cv_t<invoke_result_t<_Fn, const _Tp>>;
1403 return optional<_Up>(_Optional_func<_Fn>{__f}, std::move(_M_get()));
1405 return optional<_Up>();
1408 template<typename _Fn> requires invocable<_Fn> && copy_constructible<_Tp>
1410 or_else(_Fn&& __f) const&
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>");
1420 return std::forward<_Fn>(__f)();
1423 template<typename _Fn> requires invocable<_Fn> && move_constructible<_Tp>
1425 or_else(_Fn&& __f) &&
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>");
1433 return std::move(*this);
1435 return std::forward<_Fn>(__f)();
1439 _GLIBCXX20_CONSTEXPR void reset() noexcept { this->_M_reset(); }
1442 using _Base::_M_get;
1444 template<typename _Up> friend class optional;
1446#if __cpp_lib_optional >= 202110L // C++23
1447 template<typename _Fn, typename _Value>
1449 optional(_Optional_func<_Fn> __f, _Value&& __v)
1451 this->_M_payload._M_apply(__f, std::forward<_Value>(__v));
1456 template<typename _Tp>
1457 using __optional_relop_t =
1458 enable_if_t<is_convertible_v<_Tp, bool>, bool>;
1460 template<typename _Tp, typename _Up>
1461 using __optional_eq_t = __optional_relop_t<
1462 decltype(std::declval<const _Tp&>() == std::declval<const _Up&>())
1465 template<typename _Tp, typename _Up>
1466 using __optional_ne_t = __optional_relop_t<
1467 decltype(std::declval<const _Tp&>() != std::declval<const _Up&>())
1470 template<typename _Tp, typename _Up>
1471 using __optional_lt_t = __optional_relop_t<
1472 decltype(std::declval<const _Tp&>() < std::declval<const _Up&>())
1475 template<typename _Tp, typename _Up>
1476 using __optional_gt_t = __optional_relop_t<
1477 decltype(std::declval<const _Tp&>() > std::declval<const _Up&>())
1480 template<typename _Tp, typename _Up>
1481 using __optional_le_t = __optional_relop_t<
1482 decltype(std::declval<const _Tp&>() <= std::declval<const _Up&>())
1485 template<typename _Tp, typename _Up>
1486 using __optional_ge_t = __optional_relop_t<
1487 decltype(std::declval<const _Tp&>() >= std::declval<const _Up&>())
1490 // Comparisons between optional values.
1491 template<typename _Tp, typename _Up>
1493 operator==(const optional<_Tp>& __lhs, const optional<_Up>& __rhs)
1494 -> __optional_eq_t<_Tp, _Up>
1496 return static_cast<bool>(__lhs) == static_cast<bool>(__rhs)
1497 && (!__lhs || *__lhs == *__rhs);
1500 template<typename _Tp, typename _Up>
1502 operator!=(const optional<_Tp>& __lhs, const optional<_Up>& __rhs)
1503 -> __optional_ne_t<_Tp, _Up>
1505 return static_cast<bool>(__lhs) != static_cast<bool>(__rhs)
1506 || (static_cast<bool>(__lhs) && *__lhs != *__rhs);
1509 template<typename _Tp, typename _Up>
1511 operator<(const optional<_Tp>& __lhs, const optional<_Up>& __rhs)
1512 -> __optional_lt_t<_Tp, _Up>
1514 return static_cast<bool>(__rhs) && (!__lhs || *__lhs < *__rhs);
1517 template<typename _Tp, typename _Up>
1519 operator>(const optional<_Tp>& __lhs, const optional<_Up>& __rhs)
1520 -> __optional_gt_t<_Tp, _Up>
1522 return static_cast<bool>(__lhs) && (!__rhs || *__lhs > *__rhs);
1525 template<typename _Tp, typename _Up>
1527 operator<=(const optional<_Tp>& __lhs, const optional<_Up>& __rhs)
1528 -> __optional_le_t<_Tp, _Up>
1530 return !__lhs || (static_cast<bool>(__rhs) && *__lhs <= *__rhs);
1533 template<typename _Tp, typename _Up>
1535 operator>=(const optional<_Tp>& __lhs, const optional<_Up>& __rhs)
1536 -> __optional_ge_t<_Tp, _Up>
1538 return !__rhs || (static_cast<bool>(__lhs) && *__lhs >= *__rhs);
1541#ifdef __cpp_lib_three_way_comparison
1542 template<typename _Tp, three_way_comparable_with<_Tp> _Up>
1544 constexpr compare_three_way_result_t<_Tp, _Up>
1545 operator<=>(const optional<_Tp>& __x, const optional<_Up>& __y)
1547 return __x && __y ? *__x <=> *__y : bool(__x) <=> bool(__y);
1551 // Comparisons with nullopt.
1552 template<typename _Tp>
1555 operator==(const optional<_Tp>& __lhs, nullopt_t) noexcept
1558#ifdef __cpp_lib_three_way_comparison
1559 template<typename _Tp>
1561 constexpr strong_ordering
1562 operator<=>(const optional<_Tp>& __x, nullopt_t) noexcept
1563 { return bool(__x) <=> false; }
1565 template<typename _Tp>
1567 operator==(nullopt_t, const optional<_Tp>& __rhs) noexcept
1570 template<typename _Tp>
1572 operator!=(const optional<_Tp>& __lhs, nullopt_t) noexcept
1573 { return static_cast<bool>(__lhs); }
1575 template<typename _Tp>
1577 operator!=(nullopt_t, const optional<_Tp>& __rhs) noexcept
1578 { return static_cast<bool>(__rhs); }
1580 template<typename _Tp>
1582 operator<(const optional<_Tp>& /* __lhs */, nullopt_t) noexcept
1585 template<typename _Tp>
1587 operator<(nullopt_t, const optional<_Tp>& __rhs) noexcept
1588 { return static_cast<bool>(__rhs); }
1590 template<typename _Tp>
1592 operator>(const optional<_Tp>& __lhs, nullopt_t) noexcept
1593 { return static_cast<bool>(__lhs); }
1595 template<typename _Tp>
1597 operator>(nullopt_t, const optional<_Tp>& /* __rhs */) noexcept
1600 template<typename _Tp>
1602 operator<=(const optional<_Tp>& __lhs, nullopt_t) noexcept
1605 template<typename _Tp>
1607 operator<=(nullopt_t, const optional<_Tp>& /* __rhs */) noexcept
1610 template<typename _Tp>
1612 operator>=(const optional<_Tp>& /* __lhs */, nullopt_t) noexcept
1615 template<typename _Tp>
1617 operator>=(nullopt_t, const optional<_Tp>& __rhs) noexcept
1619#endif // three-way-comparison
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>)
1626# define _REQUIRES_NOT_OPTIONAL(T)
1629 // Comparisons with value type.
1630 template<typename _Tp, typename _Up>
1631 _REQUIRES_NOT_OPTIONAL(_Up)
1633 operator== [[nodiscard]] (const optional<_Tp>& __lhs, const _Up& __rhs)
1634 -> __optional_eq_t<_Tp, _Up>
1635 { return __lhs && *__lhs == __rhs; }
1637 template<typename _Tp, typename _Up>
1638 _REQUIRES_NOT_OPTIONAL(_Tp)
1640 operator== [[nodiscard]] (const _Tp& __lhs, const optional<_Up>& __rhs)
1641 -> __optional_eq_t<_Tp, _Up>
1642 { return __rhs && __lhs == *__rhs; }
1644 template<typename _Tp, typename _Up>
1645 _REQUIRES_NOT_OPTIONAL(_Up)
1647 operator!= [[nodiscard]] (const optional<_Tp>& __lhs, const _Up& __rhs)
1648 -> __optional_ne_t<_Tp, _Up>
1649 { return !__lhs || *__lhs != __rhs; }
1651 template<typename _Tp, typename _Up>
1652 _REQUIRES_NOT_OPTIONAL(_Tp)
1654 operator!= [[nodiscard]] (const _Tp& __lhs, const optional<_Up>& __rhs)
1655 -> __optional_ne_t<_Tp, _Up>
1656 { return !__rhs || __lhs != *__rhs; }
1658 template<typename _Tp, typename _Up>
1659 _REQUIRES_NOT_OPTIONAL(_Up)
1661 operator< [[nodiscard]] (const optional<_Tp>& __lhs, const _Up& __rhs)
1662 -> __optional_lt_t<_Tp, _Up>
1663 { return !__lhs || *__lhs < __rhs; }
1665 template<typename _Tp, typename _Up>
1666 _REQUIRES_NOT_OPTIONAL(_Tp)
1668 operator< [[nodiscard]] (const _Tp& __lhs, const optional<_Up>& __rhs)
1669 -> __optional_lt_t<_Tp, _Up>
1670 { return __rhs && __lhs < *__rhs; }
1672 template<typename _Tp, typename _Up>
1673 _REQUIRES_NOT_OPTIONAL(_Up)
1675 operator> [[nodiscard]] (const optional<_Tp>& __lhs, const _Up& __rhs)
1676 -> __optional_gt_t<_Tp, _Up>
1677 { return __lhs && *__lhs > __rhs; }
1679 template<typename _Tp, typename _Up>
1680 _REQUIRES_NOT_OPTIONAL(_Tp)
1682 operator> [[nodiscard]] (const _Tp& __lhs, const optional<_Up>& __rhs)
1683 -> __optional_gt_t<_Tp, _Up>
1684 { return !__rhs || __lhs > *__rhs; }
1686 template<typename _Tp, typename _Up>
1687 _REQUIRES_NOT_OPTIONAL(_Up)
1689 operator<= [[nodiscard]] (const optional<_Tp>& __lhs, const _Up& __rhs)
1690 -> __optional_le_t<_Tp, _Up>
1691 { return !__lhs || *__lhs <= __rhs; }
1693 template<typename _Tp, typename _Up>
1694 _REQUIRES_NOT_OPTIONAL(_Tp)
1696 operator<= [[nodiscard]] (const _Tp& __lhs, const optional<_Up>& __rhs)
1697 -> __optional_le_t<_Tp, _Up>
1698 { return __rhs && __lhs <= *__rhs; }
1700 template<typename _Tp, typename _Up>
1701 _REQUIRES_NOT_OPTIONAL(_Up)
1703 operator>= [[nodiscard]] (const optional<_Tp>& __lhs, const _Up& __rhs)
1704 -> __optional_ge_t<_Tp, _Up>
1705 { return __lhs && *__lhs >= __rhs; }
1707 template<typename _Tp, typename _Up>
1708 _REQUIRES_NOT_OPTIONAL(_Tp)
1710 operator>= [[nodiscard]] (const _Tp& __lhs, const optional<_Up>& __rhs)
1711 -> __optional_ge_t<_Tp, _Up>
1712 { return !__rhs || __lhs >= *__rhs; }
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);
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; }
1732 // Swap and creation functions.
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); }
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;
1749 template<typename _Tp>
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) }; }
1757 template<typename _Tp, typename... _Args>
1759 enable_if_t<is_constructible_v<_Tp, _Args...>,
1761 make_optional(_Args&&... __args)
1762 noexcept(is_nothrow_constructible_v<_Tp, _Args...>)
1763 { return optional<_Tp>{ in_place, std::forward<_Args>(__args)... }; }
1765 template<typename _Tp, typename _Up, typename... _Args>
1767 enable_if_t<is_constructible_v<_Tp, initializer_list<_Up>&, _Args...>,
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)... }; }
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>
1781#if __cplusplus < 202002L
1782 using result_type [[__deprecated__]] = size_t;
1783 using argument_type [[__deprecated__]] = optional<_Tp>;
1787 operator()(const optional<_Tp>& __t) const
1788 noexcept(noexcept(hash<_Up>{}(*__t)))
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;
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>>
1804 template<typename _Tp>
1805 struct __is_fast_hash<hash<optional<_Tp>>> : __is_fast_hash<hash<_Tp>>
1810#if __cpp_deduction_guides >= 201606
1811 template <typename _Tp> optional(_Tp) -> optional<_Tp>;
1814#ifdef __cpp_lib_optional_range_support // >= C++26
1815 template<typename _Tp>
1816 inline constexpr bool
1817 ranges::enable_view<optional<_Tp>> = true;
1819 template<typename _Tp>
1820 inline constexpr range_format
1821 format_kind<optional<_Tp>> = range_format::disabled;
1822#endif // __cpp_lib_optional_range_support
1824#undef _GLIBCXX_USE_CONSTRAINTS_FOR_OPTIONAL
1826_GLIBCXX_END_NAMESPACE_VERSION
1829#endif // __cpp_lib_optional
1831#endif // _GLIBCXX_OPTIONAL