| // optional<T&> -*- C++ -*- | |
| // Copyright (C) 2013-2026 Free Software Foundation, Inc. | |
| // Copyright The GNU Toolchain Authors. | |
| // | |
| // This file is part of the GNU ISO C++ Library. This library is free | |
| // software; you can redistribute it and/or modify it under the | |
| // terms of the GNU General Public License as published by the | |
| // Free Software Foundation; either version 3, or (at your option) | |
| // any later version. | |
| // This library is distributed in the hope that it will be useful, | |
| // but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| // GNU General Public License for more details. | |
| // Under Section 7 of GPL version 3, you are granted additional | |
| // permissions described in the GCC Runtime Library Exception, version | |
| // 3.1, as published by the Free Software Foundation. | |
| // You should have received a copy of the GNU General Public License and | |
| // a copy of the GCC Runtime Library Exception along with this program; | |
| // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see | |
| // <http://www.gnu.org/licenses/>. | |
| /** @file bits/optional_ref.h | |
| * This is an internal header file, included by other library headers. | |
| * Do not attempt to use it directly. @headername{optional} | |
| */ | |
| #ifndef _GLIBCXX_OPTIONAL_REF | |
| #define _GLIBCXX_OPTIONAL_REF 1 | |
| #ifdef _GLIBCXX_SYSHDR | |
| #pragma GCC system_header | |
| #endif | |
| #ifdef __glibcxx_optional // C++ >= 17 | |
| #include <type_traits> | |
| #include <bits/move.h> | |
| #include <bits/inplace_tags.h> | |
| namespace __gnu_cxx _GLIBCXX_VISIBILITY(default) | |
| { | |
| _GLIBCXX_BEGIN_NAMESPACE_VERSION | |
| template<typename _Iterator, typename _Container> | |
| class __normal_iterator; | |
| _GLIBCXX_END_NAMESPACE_VERSION | |
| } // namespace __gnu_cxx | |
| namespace std _GLIBCXX_VISIBILITY(default) | |
| { | |
| _GLIBCXX_BEGIN_NAMESPACE_VERSION | |
| /** | |
| * @addtogroup utilities | |
| * @{ | |
| */ | |
| template<typename _Tp> | |
| class optional; | |
| /// Tag type to disengage optional objects. | |
| struct nullopt_t | |
| { | |
| // Do not user-declare default constructor at all for | |
| // optional_value = {} syntax to work. | |
| // nullopt_t() = delete; | |
| // Used for constructing nullopt. | |
| enum class _Construct { _Token }; | |
| // Must be constexpr for nullopt_t to be literal. | |
| explicit constexpr nullopt_t(_Construct) noexcept { } | |
| }; | |
| /// Tag to disengage optional objects. | |
| inline constexpr nullopt_t nullopt { nullopt_t::_Construct::_Token }; | |
| template<typename _Fn> struct _Optional_func { _Fn& _M_f; }; | |
| template<typename _Tp> | |
| inline constexpr bool __is_valid_contained_type_for_optional = | |
| ( | |
| #if __glibcxx_optional >= 202506L | |
| is_lvalue_reference_v<_Tp> || | |
| #endif | |
| (is_object_v<_Tp> && is_destructible_v<_Tp> && !is_array_v<_Tp>) | |
| ) | |
| && !is_same_v<remove_cv_t<remove_reference_t<_Tp>>, nullopt_t> | |
| && !is_same_v<remove_cv_t<remove_reference_t<_Tp>>, in_place_t>; | |
| #if __glibcxx_optional >= 202506L // C++26 | |
| template<typename _Tp> | |
| class optional<_Tp&>; | |
| template<typename _Tp> | |
| constexpr bool __is_optional_ref_v = false; | |
| template<typename _Tp> | |
| constexpr bool __is_optional_ref_v<optional<_Tp&>> = true; | |
| template<typename _Tp> | |
| struct __optional_ref_base | |
| {}; | |
| #ifdef __glibcxx_optional_range_support // >= C++26 | |
| template<typename _Tp> | |
| struct __optional_ref_base<_Tp[]> | |
| {}; | |
| template<typename _Tp> | |
| requires is_object_v<_Tp> | |
| struct __optional_ref_base<_Tp> | |
| { | |
| using iterator = __gnu_cxx::__normal_iterator<_Tp*, optional<_Tp&>>; | |
| }; | |
| #endif // __glibcxx_optional_range_support | |
| template<typename _Tp> | |
| class optional<_Tp&> : public __optional_ref_base<_Tp> | |
| { | |
| static_assert(__is_valid_contained_type_for_optional<_Tp&>); | |
| public: | |
| using value_type = _Tp; | |
| constexpr static optional | |
| _S_from_ptr(_Tp* __ptr) | |
| { | |
| optional __res; | |
| __res._M_val = __ptr; | |
| return __res; | |
| } | |
| // Constructors. | |
| constexpr optional() noexcept = default; | |
| constexpr optional(nullopt_t) noexcept : optional() {} | |
| constexpr optional(const optional&) noexcept = default; | |
| template<typename _Arg> | |
| requires is_constructible_v<_Tp&, _Arg> | |
| && (!reference_constructs_from_temporary_v<_Tp&, _Arg>) | |
| explicit constexpr | |
| optional(in_place_t, _Arg&& __arg) | |
| { | |
| __convert_ref_init_val(std::forward<_Arg>(__arg)); | |
| } | |
| template<typename _Up> | |
| requires (!is_same_v<remove_cvref_t<_Up>, optional>) | |
| && (!is_same_v<remove_cvref_t<_Up>, in_place_t>) | |
| && is_constructible_v<_Tp&, _Up> | |
| && (!reference_constructs_from_temporary_v<_Tp&, _Up>) | |
| explicit(!is_convertible_v<_Up, _Tp&>) | |
| constexpr | |
| optional(_Up&& __u) | |
| noexcept(is_nothrow_constructible_v<_Tp&, _Up>) | |
| { | |
| __convert_ref_init_val(std::forward<_Up>(__u)); | |
| } | |
| template<typename _Up> | |
| requires (!is_same_v<remove_cvref_t<_Up>, optional>) | |
| && (!is_same_v<remove_cvref_t<_Up>, in_place_t>) | |
| && is_constructible_v<_Tp&, _Up> | |
| && reference_constructs_from_temporary_v<_Tp&, _Up> | |
| explicit(!is_convertible_v<_Up, _Tp&>) | |
| constexpr | |
| optional(_Up&& __u) = delete; | |
| // optional<U> & | |
| template<typename _Up> | |
| requires (!is_same_v<remove_cv_t<_Tp>, optional<_Up>>) | |
| && (!is_same_v<_Tp&, _Up>) | |
| && is_constructible_v<_Tp&, _Up&> | |
| && (!reference_constructs_from_temporary_v<_Tp&, _Up&>) | |
| explicit(!is_convertible_v<_Up&, _Tp&>) | |
| constexpr | |
| optional(optional<_Up>& __rhs) | |
| noexcept(is_nothrow_constructible_v<_Tp&, _Up&>) | |
| { | |
| if (__rhs) | |
| __convert_ref_init_val(__rhs._M_fwd()); | |
| } | |
| template<typename _Up> | |
| requires (!is_same_v<remove_cv_t<_Tp>, optional<_Up>>) | |
| && (!is_same_v<_Tp&, _Up>) | |
| && is_constructible_v<_Tp&, _Up&> | |
| && reference_constructs_from_temporary_v<_Tp&, _Up&> | |
| explicit(!is_convertible_v<_Up&, _Tp&>) | |
| constexpr | |
| optional(optional<_Up>& __rhs) = delete; | |
| // const optional<U>& | |
| template<typename _Up> | |
| requires (!is_same_v<remove_cv_t<_Tp>, optional<_Up>>) | |
| && (!is_same_v<_Tp&, _Up>) | |
| && is_constructible_v<_Tp&, const _Up&> | |
| && (!reference_constructs_from_temporary_v<_Tp&, const _Up&>) | |
| explicit(!is_convertible_v<const _Up&, _Tp&>) | |
| constexpr | |
| optional(const optional<_Up>& __rhs) | |
| noexcept(is_nothrow_constructible_v<_Tp&, _Up&>) | |
| { | |
| if (__rhs) | |
| __convert_ref_init_val(__rhs._M_fwd()); | |
| } | |
| template<typename _Up> | |
| requires (!is_same_v<remove_cv_t<_Tp>, optional<_Up>>) | |
| && (!is_same_v<_Tp&, _Up>) | |
| && is_constructible_v<_Tp&, const _Up&> | |
| && reference_constructs_from_temporary_v<_Tp&, const _Up&> | |
| explicit(!is_convertible_v<const _Up&, _Tp&>) | |
| constexpr | |
| optional(const optional<_Up>& __rhs) = delete; | |
| // optional<U>&& | |
| template<typename _Up> | |
| requires (!is_same_v<remove_cv_t<_Tp>, optional<_Up>>) | |
| && (!is_same_v<_Tp&, _Up>) | |
| && is_constructible_v<_Tp&, _Up> | |
| && (!reference_constructs_from_temporary_v<_Tp&, _Up>) | |
| explicit(!is_convertible_v<_Up, _Tp&>) | |
| constexpr | |
| optional(optional<_Up>&& __rhs) | |
| noexcept(is_nothrow_constructible_v<_Tp&, _Up>) | |
| { | |
| if (__rhs) | |
| __convert_ref_init_val(std::move(__rhs)._M_fwd()); | |
| } | |
| template<typename _Up> | |
| requires (!is_same_v<remove_cv_t<_Tp>, optional<_Up>>) | |
| && (!is_same_v<_Tp&, _Up>) | |
| && is_constructible_v<_Tp&, _Up> | |
| && reference_constructs_from_temporary_v<_Tp&, _Up> | |
| explicit(!is_convertible_v<_Up, _Tp&>) | |
| constexpr | |
| optional(optional<_Up>&& __rhs) = delete; | |
| // const optional<U>&& | |
| template<typename _Up> | |
| requires (!is_same_v<remove_cv_t<_Tp>, optional<_Up>>) | |
| && (!is_same_v<_Tp&, _Up>) | |
| && is_constructible_v<_Tp&, const _Up> | |
| && (!reference_constructs_from_temporary_v<_Tp&, _Up>) | |
| explicit(!is_convertible_v<const _Up, _Tp&>) | |
| constexpr | |
| optional(const optional<_Up>&& __rhs) | |
| noexcept(is_nothrow_constructible_v<_Tp&, const _Up>) | |
| { | |
| if (__rhs) | |
| __convert_ref_init_val(std::move(__rhs)._M_fwd()); | |
| } | |
| template<typename _Up> | |
| requires (!is_same_v<remove_cv_t<_Tp>, optional<_Up>>) | |
| && (!is_same_v<_Tp&, _Up>) | |
| && is_constructible_v<_Tp&, const _Up> | |
| && reference_constructs_from_temporary_v<_Tp&, const _Up> | |
| explicit(!is_convertible_v<const _Up, _Tp&>) | |
| constexpr | |
| optional(const optional<_Up>&& __rhs) = delete; | |
| constexpr ~optional() = default; | |
| // Assignment. | |
| constexpr optional& operator=(nullopt_t) noexcept | |
| { | |
| _M_val = nullptr; | |
| return *this; | |
| } | |
| constexpr optional& operator=(const optional&) noexcept = default; | |
| template<typename _Up> | |
| requires is_constructible_v<_Tp&, _Up> | |
| && (!reference_constructs_from_temporary_v<_Tp&, _Up>) | |
| constexpr _Tp& | |
| emplace(_Up&& __u) | |
| noexcept(is_nothrow_constructible_v<_Tp&, _Up>) | |
| { | |
| __convert_ref_init_val(std::forward<_Up>(__u)); | |
| // _GLIBCXX_RESOLVE_LIB_DEFECTS | |
| // 4300. Missing Returns: element in optional<T&>::emplace | |
| return *_M_val; | |
| } | |
| // Swap. | |
| constexpr void swap(optional& __rhs) noexcept | |
| { std::swap(_M_val, __rhs._M_val); } | |
| #ifdef __glibcxx_optional_range_support // >= C++26 | |
| // Iterator support. | |
| constexpr auto begin() const noexcept | |
| requires is_object_v<_Tp> && (!is_unbounded_array_v<_Tp>); | |
| constexpr auto end() const noexcept | |
| requires is_object_v<_Tp> && (!is_unbounded_array_v<_Tp>); | |
| #endif // __glibcxx_optional_range_support | |
| // Observers. | |
| constexpr _Tp* operator->() const noexcept | |
| { | |
| __glibcxx_assert(_M_val); // hardened precondition | |
| return _M_val; | |
| } | |
| constexpr _Tp& operator*() const noexcept | |
| { | |
| __glibcxx_assert(_M_val); // hardened precondition | |
| return *_M_val; | |
| } | |
| constexpr explicit operator bool() const noexcept | |
| { | |
| return _M_val; | |
| } | |
| constexpr bool has_value() const noexcept | |
| { | |
| return _M_val; | |
| } | |
| constexpr _Tp& value() const; | |
| // _GLIBCXX_RESOLVE_LIB_DEFECTS | |
| // 4304. std::optional<NonReturnable&> is ill-formed due to value_or | |
| template<typename _Up = remove_cv_t<_Tp>> | |
| requires is_object_v<_Tp> && (!is_array_v<_Tp>) | |
| constexpr decay_t<_Tp> | |
| value_or(_Up&& __u) const; | |
| // Monadic operations. | |
| template<typename _Fn> | |
| constexpr auto | |
| and_then(_Fn&& __f) const; | |
| template<typename _Fn> | |
| constexpr | |
| optional<remove_cv_t<invoke_result_t<_Fn, _Tp&>>> | |
| transform(_Fn&& __f) const; | |
| template<typename _Fn> | |
| requires is_invocable_v<_Fn> | |
| constexpr | |
| optional | |
| or_else(_Fn&& __f) const; | |
| // Modifiers. | |
| constexpr void reset() noexcept | |
| { | |
| _M_val = nullptr; | |
| } | |
| private: | |
| _Tp *_M_val = nullptr; | |
| [[__gnu__::__always_inline__]] | |
| constexpr _Tp& | |
| _M_fwd() const noexcept | |
| { return *_M_val; } | |
| template<typename _Up> friend class optional; | |
| template<typename _Up> | |
| constexpr | |
| void | |
| __convert_ref_init_val(_Up&& __u) | |
| noexcept | |
| { | |
| _Tp& __r(std::forward<_Up>(__u)); | |
| _M_val = std::addressof(__r); | |
| } | |
| template<typename _Fn, typename _Value> | |
| explicit constexpr | |
| optional(_Optional_func<_Fn> __f, _Value&& __v); | |
| }; | |
| #endif // __glibcxx_optional >= 202506L | |
| _GLIBCXX_END_NAMESPACE_VERSION | |
| } // namespace std | |
| #endif // __glibcxx_optional | |
| #endif // _GLIBCXX_OPTIONAL_REF |