libstdc++: optional_ref.h Source File

libstdc++

optional_ref.h
Go to the documentation of this file.
1// optional<T&> -*- C++ -*-
2
3// Copyright (C) 2013-2026 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 bits/optional_ref.h
27 * This is an internal header file, included by other library headers.
28 * Do not attempt to use it directly. @headername{optional}
29 */
30
31#ifndef _GLIBCXX_OPTIONAL_REF
32#define _GLIBCXX_OPTIONAL_REF 1
33
34#ifdef _GLIBCXX_SYSHDR
35#pragma GCC system_header
36#endif
37
38#ifdef __glibcxx_optional // C++ >= 17
39
40#include <type_traits>
41#include <bits/move.h>
42#include <bits/inplace_tags.h>
43
44namespace __gnu_cxx _GLIBCXX_VISIBILITY(default)
45{
46_GLIBCXX_BEGIN_NAMESPACE_VERSION
47
48 template<typename _Iterator, typename _Container>
49 class __normal_iterator;
50
51_GLIBCXX_END_NAMESPACE_VERSION
52} // namespace __gnu_cxx
53
54namespace std _GLIBCXX_VISIBILITY(default)
55{
56_GLIBCXX_BEGIN_NAMESPACE_VERSION
57
58 /**
59 * @addtogroup utilities
60 * @{
61 */
62
63 template<typename _Tp>
64 class optional;
65
66 /// Tag type to disengage optional objects.
67 struct nullopt_t
68 {
69 // Do not user-declare default constructor at all for
70 // optional_value = {} syntax to work.
71 // nullopt_t() = delete;
72
73 // Used for constructing nullopt.
74 enum class _Construct { _Token };
75
76 // Must be constexpr for nullopt_t to be literal.
77 explicit constexpr nullopt_t(_Construct) noexcept { }
78 };
79
80 /// Tag to disengage optional objects.
81 inline constexpr nullopt_t nullopt { nullopt_t::_Construct::_Token };
82
83 template<typename _Fn> struct _Optional_func { _Fn& _M_f; };
84
85 template<typename _Tp>
86 inline constexpr bool __is_valid_contained_type_for_optional =
87 (
88#if __glibcxx_optional >= 202506L
89 is_lvalue_reference_v<_Tp> ||
90#endif
91 (is_object_v<_Tp> && is_destructible_v<_Tp> && !is_array_v<_Tp>)
92 )
93 && !is_same_v<remove_cv_t<remove_reference_t<_Tp>>, nullopt_t>
94 && !is_same_v<remove_cv_t<remove_reference_t<_Tp>>, in_place_t>;
95
96#if __glibcxx_optional >= 202506L // C++26
97 template<typename _Tp>
98 class optional<_Tp&>;
99
100 template<typename _Tp>
101 constexpr bool __is_optional_ref_v = false;
102
103 template<typename _Tp>
104 constexpr bool __is_optional_ref_v<optional<_Tp&>> = true;
105
106 template<typename _Tp>
107 struct __optional_ref_base
108 {};
109
110#ifdef __glibcxx_optional_range_support // >= C++26
111 template<typename _Tp>
112 struct __optional_ref_base<_Tp[]>
113 {};
114
115 template<typename _Tp>
116 requires is_object_v<_Tp>
117 struct __optional_ref_base<_Tp>
118 {
119 using iterator = __gnu_cxx::__normal_iterator<_Tp*, optional<_Tp&>>;
120 };
121#endif // __glibcxx_optional_range_support
122
123 template<typename _Tp>
124 class optional<_Tp&> : public __optional_ref_base<_Tp>
125 {
126 static_assert(__is_valid_contained_type_for_optional<_Tp&>);
127
128 public:
129 using value_type = _Tp;
130
131 constexpr static optional
132 _S_from_ptr(_Tp* __ptr)
133 {
134 optional __res;
135 __res._M_val = __ptr;
136 return __res;
137 }
138
139 // Constructors.
140 constexpr optional() noexcept = default;
141 constexpr optional(nullopt_t) noexcept : optional() {}
142 constexpr optional(const optional&) noexcept = default;
143
144 template<typename _Arg>
145 requires is_constructible_v<_Tp&, _Arg>
146 && (!reference_constructs_from_temporary_v<_Tp&, _Arg>)
147 explicit constexpr
148 optional(in_place_t, _Arg&& __arg)
149 {
150 __convert_ref_init_val(std::forward<_Arg>(__arg));
151 }
152
153 template<typename _Up>
154 requires (!is_same_v<remove_cvref_t<_Up>, optional>)
155 && (!is_same_v<remove_cvref_t<_Up>, in_place_t>)
156 && is_constructible_v<_Tp&, _Up>
157 && (!reference_constructs_from_temporary_v<_Tp&, _Up>)
158 explicit(!is_convertible_v<_Up, _Tp&>)
159 constexpr
160 optional(_Up&& __u)
161 noexcept(is_nothrow_constructible_v<_Tp&, _Up>)
162 {
163 __convert_ref_init_val(std::forward<_Up>(__u));
164 }
165
166 template<typename _Up>
167 requires (!is_same_v<remove_cvref_t<_Up>, optional>)
168 && (!is_same_v<remove_cvref_t<_Up>, in_place_t>)
169 && is_constructible_v<_Tp&, _Up>
170 && reference_constructs_from_temporary_v<_Tp&, _Up>
171 explicit(!is_convertible_v<_Up, _Tp&>)
172 constexpr
173 optional(_Up&& __u) = delete;
174
175 // optional<U> &
176 template<typename _Up>
177 requires (!is_same_v<remove_cv_t<_Tp>, optional<_Up>>)
178 && (!is_same_v<_Tp&, _Up>)
179 && is_constructible_v<_Tp&, _Up&>
180 && (!reference_constructs_from_temporary_v<_Tp&, _Up&>)
181 explicit(!is_convertible_v<_Up&, _Tp&>)
182 constexpr
183 optional(optional<_Up>& __rhs)
184 noexcept(is_nothrow_constructible_v<_Tp&, _Up&>)
185 {
186 if (__rhs)
187 __convert_ref_init_val(__rhs._M_fwd());
188 }
189
190 template<typename _Up>
191 requires (!is_same_v<remove_cv_t<_Tp>, optional<_Up>>)
192 && (!is_same_v<_Tp&, _Up>)
193 && is_constructible_v<_Tp&, _Up&>
194 && reference_constructs_from_temporary_v<_Tp&, _Up&>
195 explicit(!is_convertible_v<_Up&, _Tp&>)
196 constexpr
197 optional(optional<_Up>& __rhs) = delete;
198
199 // const optional<U>&
200 template<typename _Up>
201 requires (!is_same_v<remove_cv_t<_Tp>, optional<_Up>>)
202 && (!is_same_v<_Tp&, _Up>)
203 && is_constructible_v<_Tp&, const _Up&>
204 && (!reference_constructs_from_temporary_v<_Tp&, const _Up&>)
205 explicit(!is_convertible_v<const _Up&, _Tp&>)
206 constexpr
207 optional(const optional<_Up>& __rhs)
208 noexcept(is_nothrow_constructible_v<_Tp&, _Up&>)
209 {
210 if (__rhs)
211 __convert_ref_init_val(__rhs._M_fwd());
212 }
213
214 template<typename _Up>
215 requires (!is_same_v<remove_cv_t<_Tp>, optional<_Up>>)
216 && (!is_same_v<_Tp&, _Up>)
217 && is_constructible_v<_Tp&, const _Up&>
218 && reference_constructs_from_temporary_v<_Tp&, const _Up&>
219 explicit(!is_convertible_v<const _Up&, _Tp&>)
220 constexpr
221 optional(const optional<_Up>& __rhs) = delete;
222
223 // optional<U>&&
224 template<typename _Up>
225 requires (!is_same_v<remove_cv_t<_Tp>, optional<_Up>>)
226 && (!is_same_v<_Tp&, _Up>)
227 && is_constructible_v<_Tp&, _Up>
228 && (!reference_constructs_from_temporary_v<_Tp&, _Up>)
229 explicit(!is_convertible_v<_Up, _Tp&>)
230 constexpr
231 optional(optional<_Up>&& __rhs)
232 noexcept(is_nothrow_constructible_v<_Tp&, _Up>)
233 {
234 if (__rhs)
235 __convert_ref_init_val(std::move(__rhs)._M_fwd());
236 }
237
238 template<typename _Up>
239 requires (!is_same_v<remove_cv_t<_Tp>, optional<_Up>>)
240 && (!is_same_v<_Tp&, _Up>)
241 && is_constructible_v<_Tp&, _Up>
242 && reference_constructs_from_temporary_v<_Tp&, _Up>
243 explicit(!is_convertible_v<_Up, _Tp&>)
244 constexpr
245 optional(optional<_Up>&& __rhs) = delete;
246
247 // const optional<U>&&
248 template<typename _Up>
249 requires (!is_same_v<remove_cv_t<_Tp>, optional<_Up>>)
250 && (!is_same_v<_Tp&, _Up>)
251 && is_constructible_v<_Tp&, const _Up>
252 && (!reference_constructs_from_temporary_v<_Tp&, _Up>)
253 explicit(!is_convertible_v<const _Up, _Tp&>)
254 constexpr
255 optional(const optional<_Up>&& __rhs)
256 noexcept(is_nothrow_constructible_v<_Tp&, const _Up>)
257 {
258 if (__rhs)
259 __convert_ref_init_val(std::move(__rhs)._M_fwd());
260 }
261
262 template<typename _Up>
263 requires (!is_same_v<remove_cv_t<_Tp>, optional<_Up>>)
264 && (!is_same_v<_Tp&, _Up>)
265 && is_constructible_v<_Tp&, const _Up>
266 && reference_constructs_from_temporary_v<_Tp&, const _Up>
267 explicit(!is_convertible_v<const _Up, _Tp&>)
268 constexpr
269 optional(const optional<_Up>&& __rhs) = delete;
270
271 constexpr ~optional() = default;
272
273 // Assignment.
274 constexpr optional& operator=(nullopt_t) noexcept
275 {
276 _M_val = nullptr;
277 return *this;
278 }
279
280 constexpr optional& operator=(const optional&) noexcept = default;
281
282 template<typename _Up>
283 requires is_constructible_v<_Tp&, _Up>
284 && (!reference_constructs_from_temporary_v<_Tp&, _Up>)
285 constexpr _Tp&
286 emplace(_Up&& __u)
287 noexcept(is_nothrow_constructible_v<_Tp&, _Up>)
288 {
289 __convert_ref_init_val(std::forward<_Up>(__u));
290 // _GLIBCXX_RESOLVE_LIB_DEFECTS
291 // 4300. Missing Returns: element in optional<T&>::emplace
292 return *_M_val;
293 }
294
295 // Swap.
296 constexpr void swap(optional& __rhs) noexcept
297 { std::swap(_M_val, __rhs._M_val); }
298
299#ifdef __glibcxx_optional_range_support // >= C++26
300 // Iterator support.
301 constexpr auto begin() const noexcept
302 requires is_object_v<_Tp> && (!is_unbounded_array_v<_Tp>);
303
304 constexpr auto end() const noexcept
305 requires is_object_v<_Tp> && (!is_unbounded_array_v<_Tp>);
306#endif // __glibcxx_optional_range_support
307
308 // Observers.
309 constexpr _Tp* operator->() const noexcept
310 {
311 __glibcxx_assert(_M_val); // hardened precondition
312 return _M_val;
313 }
314
315 constexpr _Tp& operator*() const noexcept
316 {
317 __glibcxx_assert(_M_val); // hardened precondition
318 return *_M_val;
319 }
320
321 constexpr explicit operator bool() const noexcept
322 {
323 return _M_val;
324 }
325
326 constexpr bool has_value() const noexcept
327 {
328 return _M_val;
329 }
330
331 constexpr _Tp& value() const;
332
333 // _GLIBCXX_RESOLVE_LIB_DEFECTS
334 // 4304. std::optional<NonReturnable&> is ill-formed due to value_or
335 template<typename _Up = remove_cv_t<_Tp>>
336 requires is_object_v<_Tp> && (!is_array_v<_Tp>)
337 constexpr decay_t<_Tp>
338 value_or(_Up&& __u) const;
339
340 // Monadic operations.
341 template<typename _Fn>
342 constexpr auto
343 and_then(_Fn&& __f) const;
344
345 template<typename _Fn>
346 constexpr
347 optional<remove_cv_t<invoke_result_t<_Fn, _Tp&>>>
348 transform(_Fn&& __f) const;
349
350 template<typename _Fn>
351 requires is_invocable_v<_Fn>
352 constexpr
353 optional
354 or_else(_Fn&& __f) const;
355
356 // Modifiers.
357 constexpr void reset() noexcept
358 {
359 _M_val = nullptr;
360 }
361
362 private:
363 _Tp *_M_val = nullptr;
364
365 [[__gnu__::__always_inline__]]
366 constexpr _Tp&
367 _M_fwd() const noexcept
368 { return *_M_val; }
369
370 template<typename _Up> friend class optional;
371
372 template<typename _Up>
373 constexpr
374 void
375 __convert_ref_init_val(_Up&& __u)
376 noexcept
377 {
378 _Tp& __r(std::forward<_Up>(__u));
379 _M_val = std::addressof(__r);
380 }
381
382 template<typename _Fn, typename _Value>
383 explicit constexpr
384 optional(_Optional_func<_Fn> __f, _Value&& __v);
385 };
386#endif // __glibcxx_optional >= 202506L
387
388_GLIBCXX_END_NAMESPACE_VERSION
389} // namespace std
390
391#endif // __glibcxx_optional
392
393#endif // _GLIBCXX_OPTIONAL_REF
type_traits
inplace_tags.h
move.h
std::operator*
constexpr complex< _Tp > operator*(const complex< _Tp > &__x, const complex< _Tp > &__y)
Return new complex value x times y.
Definition complex:434
std::remove_reference_t
typename remove_reference< _Tp >::type remove_reference_t
Alias template for remove_reference.
Definition type_traits:1913
std::decay_t
typename decay< _Tp >::type decay_t
Alias template for decay.
Definition type_traits:2965
std::addressof
constexpr _Tp * addressof(_Tp &__r) noexcept
Returns the actual address of the object or function referenced by r, even in the presence of an over...
Definition move.h:176
std::move
constexpr std::remove_reference< _Tp >::type && move(_Tp &&__t) noexcept
Convert a value to an rvalue.
Definition move.h:138
std::forward
constexpr _Tp && forward(typename std::remove_reference< _Tp >::type &__t) noexcept
Forward an lvalue.
Definition move.h:72
std::experimental::fundamentals_v1::nullopt
constexpr nullopt_t nullopt
Tag to disengage optional objects.
Definition experimental/optional:98
std
ISO C++ entities toplevel namespace is std.
std::end
constexpr auto end(_Container &__cont) noexcept(noexcept(__cont.end())) -> decltype(__cont.end())
Return an iterator pointing to one past the last element of the container.
Definition range_access.h:80
std::_Construct
constexpr void _Construct(_Tp *__p, _Args &&... __args)
Definition stl_construct.h:123
std::begin
constexpr auto begin(_Container &__cont) noexcept(noexcept(__cont.begin())) -> decltype(__cont.begin())
Return an iterator pointing to the first element of the container.
Definition range_access.h:55
__gnu_cxx
GNU extensions for public use.
std::value_type