Line data Source code
1 : // <optional> -*- C++ -*-
2 :
3 : // Copyright (C) 2013-2021 Free Software Foundation, Inc.
4 : //
5 : // This file is part of the GNU ISO C++ Library. This library is free
6 : // software; you can redistribute it and/or modify it under the
7 : // terms of the GNU General Public License as published by the
8 : // Free Software Foundation; either version 3, or (at your option)
9 : // any later version.
10 :
11 : // This library is distributed in the hope that it will be useful,
12 : // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 : // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 : // GNU General Public License for more details.
15 :
16 : // Under Section 7 of GPL version 3, you are granted additional
17 : // permissions described in the GCC Runtime Library Exception, version
18 : // 3.1, as published by the Free Software Foundation.
19 :
20 : // You should have received a copy of the GNU General Public License and
21 : // a copy of the GCC Runtime Library Exception along with this program;
22 : // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
23 : // <http://www.gnu.org/licenses/>.
24 :
25 : /** @file include/optional
26 : * This is a Standard C++ Library header.
27 : */
28 :
29 : #ifndef _GLIBCXX_OPTIONAL
30 : #define _GLIBCXX_OPTIONAL 1
31 :
32 : #pragma GCC system_header
33 :
34 : #if __cplusplus >= 201703L
35 :
36 : #include <utility>
37 : #include <type_traits>
38 : #include <exception>
39 : #include <new>
40 : #include <initializer_list>
41 : #include <bits/enable_special_members.h>
42 : #include <bits/exception_defines.h>
43 : #include <bits/functional_hash.h>
44 : #include <bits/stl_construct.h> // _Construct
45 : #if __cplusplus > 201703L
46 : # include <compare>
47 : #endif
48 :
49 : namespace std _GLIBCXX_VISIBILITY(default)
50 : {
51 : _GLIBCXX_BEGIN_NAMESPACE_VERSION
52 :
53 : /**
54 : * @addtogroup utilities
55 : * @{
56 : */
57 :
58 : #if __cplusplus == 201703L
59 : # define __cpp_lib_optional 201606L
60 : #else
61 : # define __cpp_lib_optional 202106L
62 : #endif
63 :
64 : template<typename _Tp>
65 : class optional;
66 :
67 : /// Tag type to disengage optional objects.
68 : struct nullopt_t
69 : {
70 : // Do not user-declare default constructor at all for
71 : // optional_value = {} syntax to work.
72 : // nullopt_t() = delete;
73 :
74 : // Used for constructing nullopt.
75 : enum class _Construct { _Token };
76 :
77 : // Must be constexpr for nullopt_t to be literal.
78 : explicit constexpr nullopt_t(_Construct) noexcept { }
79 : };
80 :
81 : /// Tag to disengage optional objects.
82 : inline constexpr nullopt_t nullopt { nullopt_t::_Construct::_Token };
83 :
84 : /**
85 : * @brief Exception class thrown when a disengaged optional object is
86 : * dereferenced.
87 : * @ingroup exceptions
88 : */
89 : class bad_optional_access : public exception
90 : {
91 : public:
92 0 : bad_optional_access() = default;
93 0 : virtual ~bad_optional_access() = default;
94 :
95 0 : const char* what() const noexcept override
96 0 : { return "bad optional access"; }
97 : };
98 :
99 : // XXX Does not belong here.
100 : [[__noreturn__]] inline void
101 0 : __throw_bad_optional_access()
102 0 : { _GLIBCXX_THROW_OR_ABORT(bad_optional_access()); }
103 :
104 : // This class template manages construction/destruction of
105 : // the contained value for a std::optional.
106 : template <typename _Tp>
107 : struct _Optional_payload_base
108 : {
109 : using _Stored_type = remove_const_t<_Tp>;
110 :
111 19113 : _Optional_payload_base() = default;
112 68816 : ~_Optional_payload_base() = default;
113 :
114 : template<typename... _Args>
115 : constexpr
116 32769 : _Optional_payload_base(in_place_t __tag, _Args&&... __args)
117 32769 : : _M_payload(__tag, std::forward<_Args>(__args)...),
118 32769 : _M_engaged(true)
119 32769 : { }
120 :
121 : template<typename _Up, typename... _Args>
122 : constexpr
123 : _Optional_payload_base(std::initializer_list<_Up> __il,
124 : _Args&&... __args)
125 : : _M_payload(__il, std::forward<_Args>(__args)...),
126 : _M_engaged(true)
127 : { }
128 :
129 : // Constructor used by _Optional_base copy constructor when the
130 : // contained value is not trivially copy constructible.
131 : constexpr
132 : _Optional_payload_base(bool __engaged,
133 : const _Optional_payload_base& __other)
134 : {
135 : if (__other._M_engaged)
136 : this->_M_construct(__other._M_get());
137 : }
138 :
139 : // Constructor used by _Optional_base move constructor when the
140 : // contained value is not trivially move constructible.
141 : constexpr
142 : _Optional_payload_base(bool __engaged,
143 : _Optional_payload_base&& __other)
144 : {
145 : if (__other._M_engaged)
146 : this->_M_construct(std::move(__other._M_get()));
147 : }
148 :
149 : // Copy constructor is only used to when the contained value is
150 : // trivially copy constructible.
151 : _Optional_payload_base(const _Optional_payload_base&) = default;
152 :
153 : // Move constructor is only used to when the contained value is
154 : // trivially copy constructible.
155 : _Optional_payload_base(_Optional_payload_base&&) = default;
156 :
157 : _Optional_payload_base&
158 : operator=(const _Optional_payload_base&) = default;
159 :
160 : _Optional_payload_base&
161 : operator=(_Optional_payload_base&&) = default;
162 :
163 : // used to perform non-trivial copy assignment.
164 : constexpr void
165 : _M_copy_assign(const _Optional_payload_base& __other)
166 : {
167 : if (this->_M_engaged && __other._M_engaged)
168 : this->_M_get() = __other._M_get();
169 : else
170 : {
171 : if (__other._M_engaged)
172 : this->_M_construct(__other._M_get());
173 : else
174 : this->_M_reset();
175 : }
176 : }
177 :
178 : // used to perform non-trivial move assignment.
179 : constexpr void
180 13364 : _M_move_assign(_Optional_payload_base&& __other)
181 : noexcept(__and_v<is_nothrow_move_constructible<_Tp>,
182 : is_nothrow_move_assignable<_Tp>>)
183 : {
184 13364 : if (this->_M_engaged && __other._M_engaged)
185 0 : this->_M_get() = std::move(__other._M_get());
186 : else
187 : {
188 13364 : if (__other._M_engaged)
189 23 : this->_M_construct(std::move(__other._M_get()));
190 : else
191 13341 : this->_M_reset();
192 : }
193 13364 : }
194 :
195 : struct _Empty_byte { };
196 :
197 : template<typename _Up, bool = is_trivially_destructible_v<_Up>>
198 : union _Storage
199 : {
200 315 : constexpr _Storage() noexcept : _M_empty() { }
201 :
202 : template<typename... _Args>
203 : constexpr
204 299 : _Storage(in_place_t, _Args&&... __args)
205 299 : : _M_value(std::forward<_Args>(__args)...)
206 299 : { }
207 :
208 : template<typename _Vp, typename... _Args>
209 : constexpr
210 : _Storage(std::initializer_list<_Vp> __il, _Args&&... __args)
211 : : _M_value(__il, std::forward<_Args>(__args)...)
212 : { }
213 :
214 : _Empty_byte _M_empty;
215 : _Up _M_value;
216 : };
217 :
218 : template<typename _Up>
219 : union _Storage<_Up, false>
220 : {
221 18798 : constexpr _Storage() noexcept : _M_empty() { }
222 :
223 : template<typename... _Args>
224 : constexpr
225 32470 : _Storage(in_place_t, _Args&&... __args)
226 32470 : : _M_value(std::forward<_Args>(__args)...)
227 32470 : { }
228 :
229 : template<typename _Vp, typename... _Args>
230 : constexpr
231 : _Storage(std::initializer_list<_Vp> __il, _Args&&... __args)
232 : : _M_value(__il, std::forward<_Args>(__args)...)
233 : { }
234 :
235 : // User-provided destructor is needed when _Up has non-trivial dtor.
236 68816 : _GLIBCXX20_CONSTEXPR ~_Storage() { }
237 :
238 : _Empty_byte _M_empty;
239 : _Up _M_value;
240 : };
241 :
242 : _Storage<_Stored_type> _M_payload;
243 :
244 : bool _M_engaged = false;
245 :
246 : template<typename... _Args>
247 : constexpr void
248 4221 : _M_construct(_Args&&... __args)
249 : noexcept(is_nothrow_constructible_v<_Stored_type, _Args...>)
250 : {
251 4221 : std::_Construct(std::__addressof(this->_M_payload._M_value),
252 : std::forward<_Args>(__args)...);
253 4221 : this->_M_engaged = true;
254 4221 : }
255 :
256 : constexpr void
257 34587 : _M_destroy() noexcept
258 : {
259 34587 : _M_engaged = false;
260 34587 : _M_payload._M_value.~_Stored_type();
261 34587 : }
262 :
263 : // The _M_get() operations have _M_engaged as a precondition.
264 : // They exist to access the contained value with the appropriate
265 : // const-qualification, because _M_payload has had the const removed.
266 :
267 : constexpr _Tp&
268 30559 : _M_get() noexcept
269 30559 : { return this->_M_payload._M_value; }
270 :
271 : constexpr const _Tp&
272 6411 : _M_get() const noexcept
273 6411 : { return this->_M_payload._M_value; }
274 :
275 : // _M_reset is a 'safe' operation with no precondition.
276 : constexpr void
277 84251 : _M_reset() noexcept
278 : {
279 84251 : if (this->_M_engaged)
280 34587 : _M_destroy();
281 84251 : }
282 : };
283 :
284 : // Class template that manages the payload for optionals.
285 : template <typename _Tp,
286 : bool /*_HasTrivialDestructor*/ =
287 : is_trivially_destructible_v<_Tp>,
288 : bool /*_HasTrivialCopy */ =
289 : is_trivially_copy_assignable_v<_Tp>
290 : && is_trivially_copy_constructible_v<_Tp>,
291 : bool /*_HasTrivialMove */ =
292 : is_trivially_move_assignable_v<_Tp>
293 : && is_trivially_move_constructible_v<_Tp>>
294 : struct _Optional_payload;
295 :
296 : // Payload for potentially-constexpr optionals (trivial copy/move/destroy).
297 : template <typename _Tp>
298 : struct _Optional_payload<_Tp, true, true, true>
299 : : _Optional_payload_base<_Tp>
300 : {
301 : using _Optional_payload_base<_Tp>::_Optional_payload_base;
302 :
303 315 : _Optional_payload() = default;
304 : };
305 :
306 : // Payload for optionals with non-trivial copy construction/assignment.
307 : template <typename _Tp>
308 : struct _Optional_payload<_Tp, true, false, true>
309 : : _Optional_payload_base<_Tp>
310 : {
311 : using _Optional_payload_base<_Tp>::_Optional_payload_base;
312 :
313 : _Optional_payload() = default;
314 : ~_Optional_payload() = default;
315 : _Optional_payload(const _Optional_payload&) = default;
316 : _Optional_payload(_Optional_payload&&) = default;
317 : _Optional_payload& operator=(_Optional_payload&&) = default;
318 :
319 : // Non-trivial copy assignment.
320 : constexpr
321 : _Optional_payload&
322 : operator=(const _Optional_payload& __other)
323 : {
324 : this->_M_copy_assign(__other);
325 : return *this;
326 : }
327 : };
328 :
329 : // Payload for optionals with non-trivial move construction/assignment.
330 : template <typename _Tp>
331 : struct _Optional_payload<_Tp, true, true, false>
332 : : _Optional_payload_base<_Tp>
333 : {
334 : using _Optional_payload_base<_Tp>::_Optional_payload_base;
335 :
336 : _Optional_payload() = default;
337 : ~_Optional_payload() = default;
338 : _Optional_payload(const _Optional_payload&) = default;
339 : _Optional_payload(_Optional_payload&&) = default;
340 : _Optional_payload& operator=(const _Optional_payload&) = default;
341 :
342 : // Non-trivial move assignment.
343 : constexpr
344 : _Optional_payload&
345 : operator=(_Optional_payload&& __other)
346 : noexcept(__and_v<is_nothrow_move_constructible<_Tp>,
347 : is_nothrow_move_assignable<_Tp>>)
348 : {
349 : this->_M_move_assign(std::move(__other));
350 : return *this;
351 : }
352 : };
353 :
354 : // Payload for optionals with non-trivial copy and move assignment.
355 : template <typename _Tp>
356 : struct _Optional_payload<_Tp, true, false, false>
357 : : _Optional_payload_base<_Tp>
358 : {
359 : using _Optional_payload_base<_Tp>::_Optional_payload_base;
360 :
361 18798 : _Optional_payload() = default;
362 68816 : ~_Optional_payload() = default;
363 : _Optional_payload(const _Optional_payload&) = default;
364 : _Optional_payload(_Optional_payload&&) = default;
365 :
366 : // Non-trivial copy assignment.
367 : constexpr
368 : _Optional_payload&
369 : operator=(const _Optional_payload& __other)
370 : {
371 : this->_M_copy_assign(__other);
372 : return *this;
373 : }
374 :
375 : // Non-trivial move assignment.
376 : constexpr
377 : _Optional_payload&
378 13364 : operator=(_Optional_payload&& __other)
379 : noexcept(__and_v<is_nothrow_move_constructible<_Tp>,
380 : is_nothrow_move_assignable<_Tp>>)
381 : {
382 13364 : this->_M_move_assign(std::move(__other));
383 13364 : return *this;
384 : }
385 : };
386 :
387 : // Payload for optionals with non-trivial destructors.
388 : template <typename _Tp, bool _Copy, bool _Move>
389 : struct _Optional_payload<_Tp, false, _Copy, _Move>
390 : : _Optional_payload<_Tp, true, false, false>
391 : {
392 : // Base class implements all the constructors and assignment operators:
393 : using _Optional_payload<_Tp, true, false, false>::_Optional_payload;
394 18798 : _Optional_payload() = default;
395 : _Optional_payload(const _Optional_payload&) = default;
396 : _Optional_payload(_Optional_payload&&) = default;
397 : _Optional_payload& operator=(const _Optional_payload&) = default;
398 13364 : _Optional_payload& operator=(_Optional_payload&&) = default;
399 :
400 : // Destructor needs to destroy the contained value:
401 68816 : _GLIBCXX20_CONSTEXPR ~_Optional_payload() { this->_M_reset(); }
402 : };
403 :
404 : // Common base class for _Optional_base<T> to avoid repeating these
405 : // member functions in each specialization.
406 : template<typename _Tp, typename _Dp>
407 : class _Optional_base_impl
408 : {
409 : protected:
410 : using _Stored_type = remove_const_t<_Tp>;
411 :
412 : // The _M_construct operation has !_M_engaged as a precondition
413 : // while _M_destruct has _M_engaged as a precondition.
414 : template<typename... _Args>
415 : constexpr void
416 4198 : _M_construct(_Args&&... __args)
417 : noexcept(is_nothrow_constructible_v<_Stored_type, _Args...>)
418 : {
419 4198 : static_cast<_Dp*>(this)->_M_payload._M_construct(
420 : std::forward<_Args>(__args)...);
421 4198 : }
422 :
423 : constexpr void
424 : _M_destruct() noexcept
425 : { static_cast<_Dp*>(this)->_M_payload._M_destroy(); }
426 :
427 : // _M_reset is a 'safe' operation with no precondition.
428 : constexpr void
429 2094 : _M_reset() noexcept
430 2094 : { static_cast<_Dp*>(this)->_M_payload._M_reset(); }
431 :
432 77901 : constexpr bool _M_is_engaged() const noexcept
433 77901 : { return static_cast<const _Dp*>(this)->_M_payload._M_engaged; }
434 :
435 : // The _M_get operations have _M_engaged as a precondition.
436 : constexpr _Tp&
437 30536 : _M_get() noexcept
438 : {
439 30536 : __glibcxx_assert(this->_M_is_engaged());
440 30536 : return static_cast<_Dp*>(this)->_M_payload._M_get();
441 : }
442 :
443 : constexpr const _Tp&
444 6411 : _M_get() const noexcept
445 : {
446 6411 : __glibcxx_assert(this->_M_is_engaged());
447 6411 : return static_cast<const _Dp*>(this)->_M_payload._M_get();
448 : }
449 : };
450 :
451 : /**
452 : * @brief Class template that provides copy/move constructors of optional.
453 : *
454 : * Such a separate base class template is necessary in order to
455 : * conditionally make copy/move constructors trivial.
456 : *
457 : * When the contained value is trivially copy/move constructible,
458 : * the copy/move constructors of _Optional_base will invoke the
459 : * trivial copy/move constructor of _Optional_payload. Otherwise,
460 : * they will invoke _Optional_payload(bool, const _Optional_payload&)
461 : * or _Optional_payload(bool, _Optional_payload&&) to initialize
462 : * the contained value, if copying/moving an engaged optional.
463 : *
464 : * Whether the other special members are trivial is determined by the
465 : * _Optional_payload<_Tp> specialization used for the _M_payload member.
466 : *
467 : * @see optional, _Enable_special_members
468 : */
469 : template<typename _Tp,
470 : bool = is_trivially_copy_constructible_v<_Tp>,
471 : bool = is_trivially_move_constructible_v<_Tp>>
472 : struct _Optional_base
473 : : _Optional_base_impl<_Tp, _Optional_base<_Tp>>
474 : {
475 : // Constructors for disengaged optionals.
476 18798 : constexpr _Optional_base() = default;
477 :
478 : // Constructors for engaged optionals.
479 : template<typename... _Args,
480 : enable_if_t<is_constructible_v<_Tp, _Args...>, bool> = false>
481 : constexpr explicit
482 32470 : _Optional_base(in_place_t, _Args&&... __args)
483 32470 : : _M_payload(in_place, std::forward<_Args>(__args)...)
484 32470 : { }
485 :
486 : template<typename _Up, typename... _Args,
487 : enable_if_t<is_constructible_v<_Tp,
488 : initializer_list<_Up>&,
489 : _Args...>, bool> = false>
490 : constexpr explicit
491 : _Optional_base(in_place_t,
492 : initializer_list<_Up> __il,
493 : _Args&&... __args)
494 : : _M_payload(in_place, __il, std::forward<_Args>(__args)...)
495 : { }
496 :
497 : // Copy and move constructors.
498 : constexpr
499 : _Optional_base(const _Optional_base& __other)
500 : : _M_payload(__other._M_payload._M_engaged, __other._M_payload)
501 : { }
502 :
503 : constexpr
504 : _Optional_base(_Optional_base&& __other)
505 : noexcept(is_nothrow_move_constructible_v<_Tp>)
506 : : _M_payload(__other._M_payload._M_engaged,
507 : std::move(__other._M_payload))
508 : { }
509 :
510 : // Assignment operators.
511 : _Optional_base& operator=(const _Optional_base&) = default;
512 13364 : _Optional_base& operator=(_Optional_base&&) = default;
513 :
514 : _Optional_payload<_Tp> _M_payload;
515 : };
516 :
517 : template<typename _Tp>
518 : struct _Optional_base<_Tp, false, true>
519 : : _Optional_base_impl<_Tp, _Optional_base<_Tp>>
520 : {
521 : // Constructors for disengaged optionals.
522 : constexpr _Optional_base() = default;
523 :
524 : // Constructors for engaged optionals.
525 : template<typename... _Args,
526 : enable_if_t<is_constructible_v<_Tp, _Args...>, bool> = false>
527 : constexpr explicit
528 : _Optional_base(in_place_t, _Args&&... __args)
529 : : _M_payload(in_place, std::forward<_Args>(__args)...)
530 : { }
531 :
532 : template<typename _Up, typename... _Args,
533 : enable_if_t<is_constructible_v<_Tp,
534 : initializer_list<_Up>&,
535 : _Args...>, bool> = false>
536 : constexpr explicit
537 : _Optional_base(in_place_t,
538 : initializer_list<_Up> __il,
539 : _Args... __args)
540 : : _M_payload(in_place, __il, std::forward<_Args>(__args)...)
541 : { }
542 :
543 : // Copy and move constructors.
544 : constexpr _Optional_base(const _Optional_base& __other)
545 : : _M_payload(__other._M_payload._M_engaged, __other._M_payload)
546 : { }
547 :
548 : constexpr _Optional_base(_Optional_base&& __other) = default;
549 :
550 : // Assignment operators.
551 : _Optional_base& operator=(const _Optional_base&) = default;
552 : _Optional_base& operator=(_Optional_base&&) = default;
553 :
554 : _Optional_payload<_Tp> _M_payload;
555 : };
556 :
557 : template<typename _Tp>
558 : struct _Optional_base<_Tp, true, false>
559 : : _Optional_base_impl<_Tp, _Optional_base<_Tp>>
560 : {
561 : // Constructors for disengaged optionals.
562 : constexpr _Optional_base() = default;
563 :
564 : // Constructors for engaged optionals.
565 : template<typename... _Args,
566 : enable_if_t<is_constructible_v<_Tp, _Args...>, bool> = false>
567 : constexpr explicit
568 : _Optional_base(in_place_t, _Args&&... __args)
569 : : _M_payload(in_place, std::forward<_Args>(__args)...)
570 : { }
571 :
572 : template<typename _Up, typename... _Args,
573 : enable_if_t<is_constructible_v<_Tp,
574 : initializer_list<_Up>&,
575 : _Args...>, bool> = false>
576 : constexpr explicit
577 : _Optional_base(in_place_t,
578 : initializer_list<_Up> __il,
579 : _Args&&... __args)
580 : : _M_payload(in_place, __il, std::forward<_Args>(__args)...)
581 : { }
582 :
583 : // Copy and move constructors.
584 : constexpr _Optional_base(const _Optional_base& __other) = default;
585 :
586 : constexpr
587 : _Optional_base(_Optional_base&& __other)
588 : noexcept(is_nothrow_move_constructible_v<_Tp>)
589 : : _M_payload(__other._M_payload._M_engaged,
590 : std::move(__other._M_payload))
591 : { }
592 :
593 : // Assignment operators.
594 : _Optional_base& operator=(const _Optional_base&) = default;
595 : _Optional_base& operator=(_Optional_base&&) = default;
596 :
597 : _Optional_payload<_Tp> _M_payload;
598 : };
599 :
600 : template<typename _Tp>
601 : struct _Optional_base<_Tp, true, true>
602 : : _Optional_base_impl<_Tp, _Optional_base<_Tp>>
603 : {
604 : // Constructors for disengaged optionals.
605 315 : constexpr _Optional_base() = default;
606 :
607 : // Constructors for engaged optionals.
608 : template<typename... _Args,
609 : enable_if_t<is_constructible_v<_Tp, _Args...>, bool> = false>
610 : constexpr explicit
611 299 : _Optional_base(in_place_t, _Args&&... __args)
612 299 : : _M_payload(in_place, std::forward<_Args>(__args)...)
613 299 : { }
614 :
615 : template<typename _Up, typename... _Args,
616 : enable_if_t<is_constructible_v<_Tp,
617 : initializer_list<_Up>&,
618 : _Args...>, bool> = false>
619 : constexpr explicit
620 : _Optional_base(in_place_t,
621 : initializer_list<_Up> __il,
622 : _Args&&... __args)
623 : : _M_payload(in_place, __il, std::forward<_Args>(__args)...)
624 : { }
625 :
626 : // Copy and move constructors.
627 : constexpr _Optional_base(const _Optional_base& __other) = default;
628 : constexpr _Optional_base(_Optional_base&& __other) = default;
629 :
630 : // Assignment operators.
631 : _Optional_base& operator=(const _Optional_base&) = default;
632 : _Optional_base& operator=(_Optional_base&&) = default;
633 :
634 : _Optional_payload<_Tp> _M_payload;
635 : };
636 :
637 : template<typename _Tp>
638 : class optional;
639 :
640 : template<typename _Tp, typename _Up>
641 : using __converts_from_optional =
642 : __or_<is_constructible<_Tp, const optional<_Up>&>,
643 : is_constructible<_Tp, optional<_Up>&>,
644 : is_constructible<_Tp, const optional<_Up>&&>,
645 : is_constructible<_Tp, optional<_Up>&&>,
646 : is_convertible<const optional<_Up>&, _Tp>,
647 : is_convertible<optional<_Up>&, _Tp>,
648 : is_convertible<const optional<_Up>&&, _Tp>,
649 : is_convertible<optional<_Up>&&, _Tp>>;
650 :
651 : template<typename _Tp, typename _Up>
652 : using __assigns_from_optional =
653 : __or_<is_assignable<_Tp&, const optional<_Up>&>,
654 : is_assignable<_Tp&, optional<_Up>&>,
655 : is_assignable<_Tp&, const optional<_Up>&&>,
656 : is_assignable<_Tp&, optional<_Up>&&>>;
657 :
658 : /**
659 : * @brief Class template for optional values.
660 : */
661 : template<typename _Tp>
662 : class optional
663 : : private _Optional_base<_Tp>,
664 : private _Enable_copy_move<
665 : // Copy constructor.
666 : is_copy_constructible_v<_Tp>,
667 : // Copy assignment.
668 : __and_v<is_copy_constructible<_Tp>, is_copy_assignable<_Tp>>,
669 : // Move constructor.
670 : is_move_constructible_v<_Tp>,
671 : // Move assignment.
672 : __and_v<is_move_constructible<_Tp>, is_move_assignable<_Tp>>,
673 : // Unique tag type.
674 : optional<_Tp>>
675 : {
676 : static_assert(!is_same_v<remove_cv_t<_Tp>, nullopt_t>);
677 : static_assert(!is_same_v<remove_cv_t<_Tp>, in_place_t>);
678 : static_assert(!is_reference_v<_Tp>);
679 :
680 : private:
681 : using _Base = _Optional_base<_Tp>;
682 :
683 : // SFINAE helpers
684 : template<typename _Up>
685 : using __not_self = __not_<is_same<optional, __remove_cvref_t<_Up>>>;
686 : template<typename _Up>
687 : using __not_tag = __not_<is_same<in_place_t, __remove_cvref_t<_Up>>>;
688 : template<typename... _Cond>
689 : using _Requires = enable_if_t<__and_v<_Cond...>, bool>;
690 :
691 : public:
692 : using value_type = _Tp;
693 :
694 660 : constexpr optional() noexcept { }
695 :
696 18453 : constexpr optional(nullopt_t) noexcept { }
697 :
698 : // Converting constructors for engaged optionals.
699 : template<typename _Up = _Tp,
700 : _Requires<__not_self<_Up>, __not_tag<_Up>,
701 : is_constructible<_Tp, _Up>,
702 : is_convertible<_Up, _Tp>> = true>
703 : constexpr
704 32769 : optional(_Up&& __t)
705 : noexcept(is_nothrow_constructible_v<_Tp, _Up>)
706 32769 : : _Base(std::in_place, std::forward<_Up>(__t)) { }
707 :
708 : template<typename _Up = _Tp,
709 : _Requires<__not_self<_Up>, __not_tag<_Up>,
710 : is_constructible<_Tp, _Up>,
711 : __not_<is_convertible<_Up, _Tp>>> = false>
712 : explicit constexpr
713 : optional(_Up&& __t)
714 : noexcept(is_nothrow_constructible_v<_Tp, _Up>)
715 : : _Base(std::in_place, std::forward<_Up>(__t)) { }
716 :
717 : template<typename _Up,
718 : _Requires<__not_<is_same<_Tp, _Up>>,
719 : is_constructible<_Tp, const _Up&>,
720 : is_convertible<const _Up&, _Tp>,
721 : __not_<__converts_from_optional<_Tp, _Up>>> = true>
722 : constexpr
723 : optional(const optional<_Up>& __t)
724 : noexcept(is_nothrow_constructible_v<_Tp, const _Up&>)
725 : {
726 : if (__t)
727 : emplace(*__t);
728 : }
729 :
730 : template<typename _Up,
731 : _Requires<__not_<is_same<_Tp, _Up>>,
732 : is_constructible<_Tp, const _Up&>,
733 : __not_<is_convertible<const _Up&, _Tp>>,
734 : __not_<__converts_from_optional<_Tp, _Up>>> = false>
735 : explicit constexpr
736 : optional(const optional<_Up>& __t)
737 : noexcept(is_nothrow_constructible_v<_Tp, const _Up&>)
738 : {
739 : if (__t)
740 : emplace(*__t);
741 : }
742 :
743 : template<typename _Up,
744 : _Requires<__not_<is_same<_Tp, _Up>>,
745 : is_constructible<_Tp, _Up>,
746 : is_convertible<_Up, _Tp>,
747 : __not_<__converts_from_optional<_Tp, _Up>>> = true>
748 : constexpr
749 : optional(optional<_Up>&& __t)
750 : noexcept(is_nothrow_constructible_v<_Tp, _Up>)
751 : {
752 : if (__t)
753 : emplace(std::move(*__t));
754 : }
755 :
756 : template<typename _Up,
757 : _Requires<__not_<is_same<_Tp, _Up>>,
758 : is_constructible<_Tp, _Up>,
759 : __not_<is_convertible<_Up, _Tp>>,
760 : __not_<__converts_from_optional<_Tp, _Up>>> = false>
761 : explicit constexpr
762 : optional(optional<_Up>&& __t)
763 : noexcept(is_nothrow_constructible_v<_Tp, _Up>)
764 : {
765 : if (__t)
766 : emplace(std::move(*__t));
767 : }
768 :
769 : template<typename... _Args,
770 : _Requires<is_constructible<_Tp, _Args...>> = false>
771 : explicit constexpr
772 : optional(in_place_t, _Args&&... __args)
773 : noexcept(is_nothrow_constructible_v<_Tp, _Args...>)
774 : : _Base(std::in_place, std::forward<_Args>(__args)...) { }
775 :
776 : template<typename _Up, typename... _Args,
777 : _Requires<is_constructible<_Tp,
778 : initializer_list<_Up>&,
779 : _Args...>> = false>
780 : explicit constexpr
781 : optional(in_place_t, initializer_list<_Up> __il, _Args&&... __args)
782 : noexcept(is_nothrow_constructible_v<_Tp, initializer_list<_Up>&,
783 : _Args...>)
784 : : _Base(std::in_place, __il, std::forward<_Args>(__args)...) { }
785 :
786 :
787 : // Assignment operators.
788 : _GLIBCXX20_CONSTEXPR optional&
789 2081 : operator=(nullopt_t) noexcept
790 : {
791 2081 : this->_M_reset();
792 2081 : return *this;
793 : }
794 :
795 : template<typename _Up = _Tp>
796 : _GLIBCXX20_CONSTEXPR
797 : enable_if_t<__and_v<__not_self<_Up>,
798 : __not_<__and_<is_scalar<_Tp>,
799 : is_same<_Tp, decay_t<_Up>>>>,
800 : is_constructible<_Tp, _Up>,
801 : is_assignable<_Tp&, _Up>>,
802 : optional&>
803 4198 : operator=(_Up&& __u)
804 : noexcept(__and_v<is_nothrow_constructible<_Tp, _Up>,
805 : is_nothrow_assignable<_Tp&, _Up>>)
806 : {
807 4198 : if (this->_M_is_engaged())
808 0 : this->_M_get() = std::forward<_Up>(__u);
809 : else
810 4198 : this->_M_construct(std::forward<_Up>(__u));
811 :
812 4198 : return *this;
813 : }
814 :
815 : template<typename _Up>
816 : _GLIBCXX20_CONSTEXPR
817 : enable_if_t<__and_v<__not_<is_same<_Tp, _Up>>,
818 : is_constructible<_Tp, const _Up&>,
819 : is_assignable<_Tp&, const _Up&>,
820 : __not_<__converts_from_optional<_Tp, _Up>>,
821 : __not_<__assigns_from_optional<_Tp, _Up>>>,
822 : optional&>
823 : operator=(const optional<_Up>& __u)
824 : noexcept(__and_v<is_nothrow_constructible<_Tp, const _Up&>,
825 : is_nothrow_assignable<_Tp&, const _Up&>>)
826 : {
827 : if (__u)
828 : {
829 : if (this->_M_is_engaged())
830 : this->_M_get() = *__u;
831 : else
832 : this->_M_construct(*__u);
833 : }
834 : else
835 : {
836 : this->_M_reset();
837 : }
838 : return *this;
839 : }
840 :
841 : template<typename _Up>
842 : _GLIBCXX20_CONSTEXPR
843 : enable_if_t<__and_v<__not_<is_same<_Tp, _Up>>,
844 : is_constructible<_Tp, _Up>,
845 : is_assignable<_Tp&, _Up>,
846 : __not_<__converts_from_optional<_Tp, _Up>>,
847 : __not_<__assigns_from_optional<_Tp, _Up>>>,
848 : optional&>
849 : operator=(optional<_Up>&& __u)
850 : noexcept(__and_v<is_nothrow_constructible<_Tp, _Up>,
851 : is_nothrow_assignable<_Tp&, _Up>>)
852 : {
853 : if (__u)
854 : {
855 : if (this->_M_is_engaged())
856 : this->_M_get() = std::move(*__u);
857 : else
858 : this->_M_construct(std::move(*__u));
859 : }
860 : else
861 : {
862 : this->_M_reset();
863 : }
864 :
865 : return *this;
866 : }
867 :
868 : template<typename... _Args>
869 : _GLIBCXX20_CONSTEXPR
870 : enable_if_t<is_constructible_v<_Tp, _Args...>, _Tp&>
871 : emplace(_Args&&... __args)
872 : noexcept(is_nothrow_constructible_v<_Tp, _Args...>)
873 : {
874 : this->_M_reset();
875 : this->_M_construct(std::forward<_Args>(__args)...);
876 : return this->_M_get();
877 : }
878 :
879 : template<typename _Up, typename... _Args>
880 : _GLIBCXX20_CONSTEXPR
881 : enable_if_t<is_constructible_v<_Tp, initializer_list<_Up>&, _Args...>,
882 : _Tp&>
883 : emplace(initializer_list<_Up> __il, _Args&&... __args)
884 : noexcept(is_nothrow_constructible_v<_Tp, initializer_list<_Up>&,
885 : _Args...>)
886 : {
887 : this->_M_reset();
888 : this->_M_construct(__il, std::forward<_Args>(__args)...);
889 : return this->_M_get();
890 : }
891 :
892 : // Destructor is implicit, implemented in _Optional_base.
893 :
894 : // Swap.
895 : _GLIBCXX20_CONSTEXPR void
896 : swap(optional& __other)
897 : noexcept(is_nothrow_move_constructible_v<_Tp>
898 : && is_nothrow_swappable_v<_Tp>)
899 : {
900 : using std::swap;
901 :
902 : if (this->_M_is_engaged() && __other._M_is_engaged())
903 : swap(this->_M_get(), __other._M_get());
904 : else if (this->_M_is_engaged())
905 : {
906 : __other._M_construct(std::move(this->_M_get()));
907 : this->_M_destruct();
908 : }
909 : else if (__other._M_is_engaged())
910 : {
911 : this->_M_construct(std::move(__other._M_get()));
912 : __other._M_destruct();
913 : }
914 : }
915 :
916 : // Observers.
917 : constexpr const _Tp*
918 4164 : operator->() const noexcept
919 4164 : { return std::__addressof(this->_M_get()); }
920 :
921 : constexpr _Tp*
922 4238 : operator->() noexcept
923 4238 : { return std::__addressof(this->_M_get()); }
924 :
925 : constexpr const _Tp&
926 2247 : operator*() const& noexcept
927 2247 : { return this->_M_get(); }
928 :
929 : constexpr _Tp&
930 19855 : operator*()& noexcept
931 19855 : { return this->_M_get(); }
932 :
933 : constexpr _Tp&&
934 : operator*()&& noexcept
935 : { return std::move(this->_M_get()); }
936 :
937 : constexpr const _Tp&&
938 : operator*() const&& noexcept
939 : { return std::move(this->_M_get()); }
940 :
941 60816 : constexpr explicit operator bool() const noexcept
942 60816 : { return this->_M_is_engaged(); }
943 :
944 6444 : constexpr bool has_value() const noexcept
945 6444 : { return this->_M_is_engaged(); }
946 :
947 : constexpr const _Tp&
948 : value() const&
949 : {
950 : if (this->_M_is_engaged())
951 : return this->_M_get();
952 : __throw_bad_optional_access();
953 : }
954 :
955 : constexpr _Tp&
956 6443 : value()&
957 : {
958 6443 : if (this->_M_is_engaged())
959 6443 : return this->_M_get();
960 0 : __throw_bad_optional_access();
961 : }
962 :
963 : constexpr _Tp&&
964 : value()&&
965 : {
966 : if (this->_M_is_engaged())
967 : return std::move(this->_M_get());
968 : __throw_bad_optional_access();
969 : }
970 :
971 : constexpr const _Tp&&
972 : value() const&&
973 : {
974 : if (this->_M_is_engaged())
975 : return std::move(this->_M_get());
976 : __throw_bad_optional_access();
977 : }
978 :
979 : template<typename _Up>
980 : constexpr _Tp
981 : value_or(_Up&& __u) const&
982 : {
983 : static_assert(is_copy_constructible_v<_Tp>);
984 : static_assert(is_convertible_v<_Up&&, _Tp>);
985 :
986 : if (this->_M_is_engaged())
987 : return this->_M_get();
988 : else
989 : return static_cast<_Tp>(std::forward<_Up>(__u));
990 : }
991 :
992 : template<typename _Up>
993 : constexpr _Tp
994 : value_or(_Up&& __u) &&
995 : {
996 : static_assert(is_move_constructible_v<_Tp>);
997 : static_assert(is_convertible_v<_Up&&, _Tp>);
998 :
999 : if (this->_M_is_engaged())
1000 : return std::move(this->_M_get());
1001 : else
1002 : return static_cast<_Tp>(std::forward<_Up>(__u));
1003 : }
1004 :
1005 13 : _GLIBCXX20_CONSTEXPR void reset() noexcept { this->_M_reset(); }
1006 : };
1007 :
1008 : template<typename _Tp>
1009 : using __optional_relop_t =
1010 : enable_if_t<is_convertible<_Tp, bool>::value, bool>;
1011 :
1012 : template<typename _Tp, typename _Up>
1013 : using __optional_eq_t = __optional_relop_t<
1014 : decltype(std::declval<const _Tp&>() == std::declval<const _Up&>())
1015 : >;
1016 :
1017 : template<typename _Tp, typename _Up>
1018 : using __optional_ne_t = __optional_relop_t<
1019 : decltype(std::declval<const _Tp&>() != std::declval<const _Up&>())
1020 : >;
1021 :
1022 : template<typename _Tp, typename _Up>
1023 : using __optional_lt_t = __optional_relop_t<
1024 : decltype(std::declval<const _Tp&>() < std::declval<const _Up&>())
1025 : >;
1026 :
1027 : template<typename _Tp, typename _Up>
1028 : using __optional_gt_t = __optional_relop_t<
1029 : decltype(std::declval<const _Tp&>() > std::declval<const _Up&>())
1030 : >;
1031 :
1032 : template<typename _Tp, typename _Up>
1033 : using __optional_le_t = __optional_relop_t<
1034 : decltype(std::declval<const _Tp&>() <= std::declval<const _Up&>())
1035 : >;
1036 :
1037 : template<typename _Tp, typename _Up>
1038 : using __optional_ge_t = __optional_relop_t<
1039 : decltype(std::declval<const _Tp&>() >= std::declval<const _Up&>())
1040 : >;
1041 :
1042 : // Comparisons between optional values.
1043 : template<typename _Tp, typename _Up>
1044 : constexpr auto
1045 : operator==(const optional<_Tp>& __lhs, const optional<_Up>& __rhs)
1046 : -> __optional_eq_t<_Tp, _Up>
1047 : {
1048 : return static_cast<bool>(__lhs) == static_cast<bool>(__rhs)
1049 : && (!__lhs || *__lhs == *__rhs);
1050 : }
1051 :
1052 : template<typename _Tp, typename _Up>
1053 : constexpr auto
1054 : operator!=(const optional<_Tp>& __lhs, const optional<_Up>& __rhs)
1055 : -> __optional_ne_t<_Tp, _Up>
1056 : {
1057 : return static_cast<bool>(__lhs) != static_cast<bool>(__rhs)
1058 : || (static_cast<bool>(__lhs) && *__lhs != *__rhs);
1059 : }
1060 :
1061 : template<typename _Tp, typename _Up>
1062 : constexpr auto
1063 : operator<(const optional<_Tp>& __lhs, const optional<_Up>& __rhs)
1064 : -> __optional_lt_t<_Tp, _Up>
1065 : {
1066 : return static_cast<bool>(__rhs) && (!__lhs || *__lhs < *__rhs);
1067 : }
1068 :
1069 : template<typename _Tp, typename _Up>
1070 : constexpr auto
1071 : operator>(const optional<_Tp>& __lhs, const optional<_Up>& __rhs)
1072 : -> __optional_gt_t<_Tp, _Up>
1073 : {
1074 : return static_cast<bool>(__lhs) && (!__rhs || *__lhs > *__rhs);
1075 : }
1076 :
1077 : template<typename _Tp, typename _Up>
1078 : constexpr auto
1079 : operator<=(const optional<_Tp>& __lhs, const optional<_Up>& __rhs)
1080 : -> __optional_le_t<_Tp, _Up>
1081 : {
1082 : return !__lhs || (static_cast<bool>(__rhs) && *__lhs <= *__rhs);
1083 : }
1084 :
1085 : template<typename _Tp, typename _Up>
1086 : constexpr auto
1087 : operator>=(const optional<_Tp>& __lhs, const optional<_Up>& __rhs)
1088 : -> __optional_ge_t<_Tp, _Up>
1089 : {
1090 : return !__rhs || (static_cast<bool>(__lhs) && *__lhs >= *__rhs);
1091 : }
1092 :
1093 : #ifdef __cpp_lib_three_way_comparison
1094 : template<typename _Tp, three_way_comparable_with<_Tp> _Up>
1095 : constexpr compare_three_way_result_t<_Tp, _Up>
1096 : operator<=>(const optional<_Tp>& __x, const optional<_Up>& __y)
1097 : {
1098 : return __x && __y ? *__x <=> *__y : bool(__x) <=> bool(__y);
1099 : }
1100 : #endif
1101 :
1102 : // Comparisons with nullopt.
1103 : template<typename _Tp>
1104 : constexpr bool
1105 17332 : operator==(const optional<_Tp>& __lhs, nullopt_t) noexcept
1106 17332 : { return !__lhs; }
1107 :
1108 : #ifdef __cpp_lib_three_way_comparison
1109 : template<typename _Tp>
1110 : constexpr strong_ordering
1111 : operator<=>(const optional<_Tp>& __x, nullopt_t) noexcept
1112 : { return bool(__x) <=> false; }
1113 : #else
1114 : template<typename _Tp>
1115 : constexpr bool
1116 : operator==(nullopt_t, const optional<_Tp>& __rhs) noexcept
1117 : { return !__rhs; }
1118 :
1119 : template<typename _Tp>
1120 : constexpr bool
1121 35295 : operator!=(const optional<_Tp>& __lhs, nullopt_t) noexcept
1122 35295 : { return static_cast<bool>(__lhs); }
1123 :
1124 : template<typename _Tp>
1125 : constexpr bool
1126 : operator!=(nullopt_t, const optional<_Tp>& __rhs) noexcept
1127 : { return static_cast<bool>(__rhs); }
1128 :
1129 : template<typename _Tp>
1130 : constexpr bool
1131 : operator<(const optional<_Tp>& /* __lhs */, nullopt_t) noexcept
1132 : { return false; }
1133 :
1134 : template<typename _Tp>
1135 : constexpr bool
1136 : operator<(nullopt_t, const optional<_Tp>& __rhs) noexcept
1137 : { return static_cast<bool>(__rhs); }
1138 :
1139 : template<typename _Tp>
1140 : constexpr bool
1141 : operator>(const optional<_Tp>& __lhs, nullopt_t) noexcept
1142 : { return static_cast<bool>(__lhs); }
1143 :
1144 : template<typename _Tp>
1145 : constexpr bool
1146 : operator>(nullopt_t, const optional<_Tp>& /* __rhs */) noexcept
1147 : { return false; }
1148 :
1149 : template<typename _Tp>
1150 : constexpr bool
1151 : operator<=(const optional<_Tp>& __lhs, nullopt_t) noexcept
1152 : { return !__lhs; }
1153 :
1154 : template<typename _Tp>
1155 : constexpr bool
1156 : operator<=(nullopt_t, const optional<_Tp>& /* __rhs */) noexcept
1157 : { return true; }
1158 :
1159 : template<typename _Tp>
1160 : constexpr bool
1161 : operator>=(const optional<_Tp>& /* __lhs */, nullopt_t) noexcept
1162 : { return true; }
1163 :
1164 : template<typename _Tp>
1165 : constexpr bool
1166 : operator>=(nullopt_t, const optional<_Tp>& __rhs) noexcept
1167 : { return !__rhs; }
1168 : #endif // three-way-comparison
1169 :
1170 : // Comparisons with value type.
1171 : template<typename _Tp, typename _Up>
1172 : constexpr auto
1173 143 : operator==(const optional<_Tp>& __lhs, const _Up& __rhs)
1174 : -> __optional_eq_t<_Tp, _Up>
1175 143 : { return __lhs && *__lhs == __rhs; }
1176 :
1177 : template<typename _Tp, typename _Up>
1178 : constexpr auto
1179 : operator==(const _Up& __lhs, const optional<_Tp>& __rhs)
1180 : -> __optional_eq_t<_Up, _Tp>
1181 : { return __rhs && __lhs == *__rhs; }
1182 :
1183 : template<typename _Tp, typename _Up>
1184 : constexpr auto
1185 : operator!=(const optional<_Tp>& __lhs, const _Up& __rhs)
1186 : -> __optional_ne_t<_Tp, _Up>
1187 : { return !__lhs || *__lhs != __rhs; }
1188 :
1189 : template<typename _Tp, typename _Up>
1190 : constexpr auto
1191 : operator!=(const _Up& __lhs, const optional<_Tp>& __rhs)
1192 : -> __optional_ne_t<_Up, _Tp>
1193 : { return !__rhs || __lhs != *__rhs; }
1194 :
1195 : template<typename _Tp, typename _Up>
1196 : constexpr auto
1197 : operator<(const optional<_Tp>& __lhs, const _Up& __rhs)
1198 : -> __optional_lt_t<_Tp, _Up>
1199 : { return !__lhs || *__lhs < __rhs; }
1200 :
1201 : template<typename _Tp, typename _Up>
1202 : constexpr auto
1203 : operator<(const _Up& __lhs, const optional<_Tp>& __rhs)
1204 : -> __optional_lt_t<_Up, _Tp>
1205 : { return __rhs && __lhs < *__rhs; }
1206 :
1207 : template<typename _Tp, typename _Up>
1208 : constexpr auto
1209 : operator>(const optional<_Tp>& __lhs, const _Up& __rhs)
1210 : -> __optional_gt_t<_Tp, _Up>
1211 : { return __lhs && *__lhs > __rhs; }
1212 :
1213 : template<typename _Tp, typename _Up>
1214 : constexpr auto
1215 : operator>(const _Up& __lhs, const optional<_Tp>& __rhs)
1216 : -> __optional_gt_t<_Up, _Tp>
1217 : { return !__rhs || __lhs > *__rhs; }
1218 :
1219 : template<typename _Tp, typename _Up>
1220 : constexpr auto
1221 : operator<=(const optional<_Tp>& __lhs, const _Up& __rhs)
1222 : -> __optional_le_t<_Tp, _Up>
1223 : { return !__lhs || *__lhs <= __rhs; }
1224 :
1225 : template<typename _Tp, typename _Up>
1226 : constexpr auto
1227 : operator<=(const _Up& __lhs, const optional<_Tp>& __rhs)
1228 : -> __optional_le_t<_Up, _Tp>
1229 : { return __rhs && __lhs <= *__rhs; }
1230 :
1231 : template<typename _Tp, typename _Up>
1232 : constexpr auto
1233 : operator>=(const optional<_Tp>& __lhs, const _Up& __rhs)
1234 : -> __optional_ge_t<_Tp, _Up>
1235 : { return __lhs && *__lhs >= __rhs; }
1236 :
1237 : template<typename _Tp, typename _Up>
1238 : constexpr auto
1239 : operator>=(const _Up& __lhs, const optional<_Tp>& __rhs)
1240 : -> __optional_ge_t<_Up, _Tp>
1241 : { return !__rhs || __lhs >= *__rhs; }
1242 :
1243 : #ifdef __cpp_lib_three_way_comparison
1244 : template<typename _Tp>
1245 : inline constexpr bool __is_optional_v = false;
1246 : template<typename _Tp>
1247 : inline constexpr bool __is_optional_v<optional<_Tp>> = true;
1248 :
1249 : template<typename _Tp, typename _Up>
1250 : requires (!__is_optional_v<_Up>)
1251 : && three_way_comparable_with<_Tp, _Up>
1252 : constexpr compare_three_way_result_t<_Tp, _Up>
1253 : operator<=>(const optional<_Tp>& __x, const _Up& __v)
1254 : { return bool(__x) ? *__x <=> __v : strong_ordering::less; }
1255 : #endif
1256 :
1257 : // Swap and creation functions.
1258 :
1259 : // _GLIBCXX_RESOLVE_LIB_DEFECTS
1260 : // 2748. swappable traits for optionals
1261 : template<typename _Tp>
1262 : _GLIBCXX20_CONSTEXPR
1263 : inline enable_if_t<is_move_constructible_v<_Tp> && is_swappable_v<_Tp>>
1264 : swap(optional<_Tp>& __lhs, optional<_Tp>& __rhs)
1265 : noexcept(noexcept(__lhs.swap(__rhs)))
1266 : { __lhs.swap(__rhs); }
1267 :
1268 : template<typename _Tp>
1269 : enable_if_t<!(is_move_constructible_v<_Tp> && is_swappable_v<_Tp>)>
1270 : swap(optional<_Tp>&, optional<_Tp>&) = delete;
1271 :
1272 : template<typename _Tp>
1273 : constexpr
1274 : enable_if_t<is_constructible_v<decay_t<_Tp>, _Tp>,
1275 : optional<decay_t<_Tp>>>
1276 : make_optional(_Tp&& __t)
1277 : noexcept(is_nothrow_constructible_v<optional<decay_t<_Tp>>, _Tp>)
1278 : { return optional<decay_t<_Tp>>{ std::forward<_Tp>(__t) }; }
1279 :
1280 : template<typename _Tp, typename... _Args>
1281 : constexpr
1282 : enable_if_t<is_constructible_v<_Tp, _Args...>,
1283 : optional<_Tp>>
1284 : make_optional(_Args&&... __args)
1285 : noexcept(is_nothrow_constructible_v<_Tp, _Args...>)
1286 : { return optional<_Tp>{ in_place, std::forward<_Args>(__args)... }; }
1287 :
1288 : template<typename _Tp, typename _Up, typename... _Args>
1289 : constexpr
1290 : enable_if_t<is_constructible_v<_Tp, initializer_list<_Up>&, _Args...>,
1291 : optional<_Tp>>
1292 : make_optional(initializer_list<_Up> __il, _Args&&... __args)
1293 : noexcept(is_nothrow_constructible_v<_Tp, initializer_list<_Up>&, _Args...>)
1294 : { return optional<_Tp>{ in_place, __il, std::forward<_Args>(__args)... }; }
1295 :
1296 : // Hash.
1297 :
1298 : template<typename _Tp, typename _Up = remove_const_t<_Tp>,
1299 : bool = __poison_hash<_Up>::__enable_hash_call>
1300 : struct __optional_hash_call_base
1301 : {
1302 : size_t
1303 : operator()(const optional<_Tp>& __t) const
1304 : noexcept(noexcept(hash<_Up>{}(*__t)))
1305 : {
1306 : // We pick an arbitrary hash for disengaged optionals which hopefully
1307 : // usual values of _Tp won't typically hash to.
1308 : constexpr size_t __magic_disengaged_hash = static_cast<size_t>(-3333);
1309 : return __t ? hash<_Up>{}(*__t) : __magic_disengaged_hash;
1310 : }
1311 : };
1312 :
1313 : template<typename _Tp, typename _Up>
1314 : struct __optional_hash_call_base<_Tp, _Up, false> {};
1315 :
1316 : template<typename _Tp>
1317 : struct hash<optional<_Tp>>
1318 : : private __poison_hash<remove_const_t<_Tp>>,
1319 : public __optional_hash_call_base<_Tp>
1320 : {
1321 : using result_type [[__deprecated__]] = size_t;
1322 : using argument_type [[__deprecated__]] = optional<_Tp>;
1323 : };
1324 :
1325 : template<typename _Tp>
1326 : struct __is_fast_hash<hash<optional<_Tp>>> : __is_fast_hash<hash<_Tp>>
1327 : { };
1328 :
1329 : /// @}
1330 :
1331 : #if __cpp_deduction_guides >= 201606
1332 : template <typename _Tp> optional(_Tp) -> optional<_Tp>;
1333 : #endif
1334 :
1335 : _GLIBCXX_END_NAMESPACE_VERSION
1336 : } // namespace std
1337 :
1338 : #endif // C++17
1339 :
1340 : #endif // _GLIBCXX_OPTIONAL
|