Line data Source code
1 : // <optional> -*- C++ -*-
2 :
3 : // Copyright (C) 2013-2018 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 <stdexcept>
39 : #include <new>
40 : #include <initializer_list>
41 : #include <bits/functexcept.h>
42 : #include <bits/functional_hash.h>
43 : #include <bits/enable_special_members.h>
44 :
45 : namespace std _GLIBCXX_VISIBILITY(default)
46 : {
47 : _GLIBCXX_BEGIN_NAMESPACE_VERSION
48 :
49 : /**
50 : * @addtogroup utilities
51 : * @{
52 : */
53 :
54 : #define __cpp_lib_optional 201606L
55 :
56 : template<typename _Tp>
57 : class optional;
58 :
59 : /// Tag type to disengage optional objects.
60 : struct nullopt_t
61 : {
62 : // Do not user-declare default constructor at all for
63 : // optional_value = {} syntax to work.
64 : // nullopt_t() = delete;
65 :
66 : // Used for constructing nullopt.
67 : enum class _Construct { _Token };
68 :
69 : // Must be constexpr for nullopt_t to be literal.
70 : explicit constexpr nullopt_t(_Construct) { }
71 : };
72 :
73 : /// Tag to disengage optional objects.
74 : inline constexpr nullopt_t nullopt { nullopt_t::_Construct::_Token };
75 :
76 : /**
77 : * @brief Exception class thrown when a disengaged optional object is
78 : * dereferenced.
79 : * @ingroup exceptions
80 : */
81 : class bad_optional_access : public exception
82 : {
83 : public:
84 : bad_optional_access() { }
85 :
86 : virtual const char* what() const noexcept override
87 : { return "bad optional access"; }
88 :
89 : virtual ~bad_optional_access() noexcept = default;
90 : };
91 :
92 : void
93 : __throw_bad_optional_access()
94 : __attribute__((__noreturn__));
95 :
96 : // XXX Does not belong here.
97 : inline void
98 : __throw_bad_optional_access()
99 : { _GLIBCXX_THROW_OR_ABORT(bad_optional_access()); }
100 :
101 :
102 : // Payload for optionals with non-trivial destructor.
103 : template <typename _Tp,
104 : bool /*_HasTrivialDestructor*/ =
105 : is_trivially_destructible_v<_Tp>,
106 : bool /*_HasTrivialCopy */ =
107 : is_trivially_copy_assignable_v<_Tp>
108 : && is_trivially_copy_constructible_v<_Tp>,
109 : bool /*_HasTrivialMove */ =
110 : is_trivially_move_assignable_v<_Tp>
111 : && is_trivially_move_constructible_v<_Tp>>
112 : struct _Optional_payload
113 : {
114 : constexpr _Optional_payload() noexcept : _M_empty() { }
115 :
116 : template <typename... _Args>
117 : constexpr
118 176 : _Optional_payload(in_place_t, _Args&&... __args)
119 176 : : _M_payload(std::forward<_Args>(__args)...), _M_engaged(true) { }
120 :
121 : template<typename _Up, typename... _Args>
122 : constexpr
123 : _Optional_payload(std::initializer_list<_Up> __il,
124 : _Args&&... __args)
125 : : _M_payload(__il, std::forward<_Args>(__args)...),
126 : _M_engaged(true)
127 : { }
128 :
129 : constexpr
130 : _Optional_payload(bool __engaged, const _Optional_payload& __other)
131 : : _Optional_payload(__other)
132 : { }
133 :
134 : constexpr
135 : _Optional_payload(bool __engaged, _Optional_payload&& __other)
136 : : _Optional_payload(std::move(__other))
137 : { }
138 :
139 : constexpr
140 : _Optional_payload(const _Optional_payload& __other)
141 : {
142 : if (__other._M_engaged)
143 : this->_M_construct(__other._M_payload);
144 : }
145 :
146 : constexpr
147 : _Optional_payload(_Optional_payload&& __other)
148 : {
149 : if (__other._M_engaged)
150 : this->_M_construct(std::move(__other._M_payload));
151 : }
152 :
153 : constexpr
154 : _Optional_payload&
155 : operator=(const _Optional_payload& __other)
156 : {
157 : if (this->_M_engaged && __other._M_engaged)
158 : this->_M_get() = __other._M_get();
159 : else
160 : {
161 : if (__other._M_engaged)
162 : this->_M_construct(__other._M_get());
163 : else
164 : this->_M_reset();
165 : }
166 : return *this;
167 : }
168 :
169 : constexpr
170 : _Optional_payload&
171 : operator=(_Optional_payload&& __other)
172 : noexcept(__and_<is_nothrow_move_constructible<_Tp>,
173 : is_nothrow_move_assignable<_Tp>>())
174 : {
175 : if (this->_M_engaged && __other._M_engaged)
176 : this->_M_get() = std::move(__other._M_get());
177 : else
178 : {
179 : if (__other._M_engaged)
180 : this->_M_construct(std::move(__other._M_get()));
181 : else
182 : this->_M_reset();
183 : }
184 : return *this;
185 : }
186 :
187 : using _Stored_type = remove_const_t<_Tp>;
188 :
189 : struct _Empty_byte { };
190 :
191 : union {
192 : _Empty_byte _M_empty;
193 : _Stored_type _M_payload;
194 : };
195 : bool _M_engaged = false;
196 :
197 176 : ~_Optional_payload()
198 : {
199 176 : if (_M_engaged)
200 176 : _M_payload.~_Stored_type();
201 176 : }
202 :
203 : template<typename... _Args>
204 : void
205 : _M_construct(_Args&&... __args)
206 : noexcept(is_nothrow_constructible<_Stored_type, _Args...>())
207 : {
208 : ::new ((void *) std::__addressof(this->_M_payload))
209 : _Stored_type(std::forward<_Args>(__args)...);
210 : this->_M_engaged = true;
211 : }
212 :
213 : // The _M_get operations have _M_engaged as a precondition.
214 : constexpr _Tp&
215 : _M_get() noexcept
216 : { return this->_M_payload; }
217 :
218 : constexpr const _Tp&
219 : _M_get() const noexcept
220 : { return this->_M_payload; }
221 :
222 : // _M_reset is a 'safe' operation with no precondition.
223 : constexpr
224 : void
225 : _M_reset() noexcept
226 : {
227 : if (this->_M_engaged)
228 : {
229 : this->_M_engaged = false;
230 : this->_M_payload.~_Stored_type();
231 : }
232 : }
233 : };
234 :
235 : // Payload for potentially-constexpr optionals.
236 : template <typename _Tp>
237 : struct _Optional_payload<_Tp, true, true, true>
238 : {
239 : constexpr _Optional_payload() noexcept
240 : : _M_empty(), _M_engaged(false) { }
241 :
242 : template<typename... _Args>
243 : constexpr
244 : _Optional_payload(in_place_t, _Args&&... __args)
245 : : _M_payload(std::forward<_Args>(__args)...), _M_engaged(true)
246 : { }
247 :
248 : template<typename _Up, typename... _Args>
249 : constexpr
250 : _Optional_payload(std::initializer_list<_Up> __il,
251 : _Args&&... __args)
252 : : _M_payload(__il, std::forward<_Args>(__args)...),
253 : _M_engaged(true)
254 : { }
255 :
256 : constexpr
257 : _Optional_payload(bool __engaged, const _Optional_payload& __other)
258 : : _M_engaged(__engaged)
259 : {
260 : if (__engaged)
261 : _M_construct(__other._M_get());
262 : }
263 :
264 : constexpr
265 : _Optional_payload(bool __engaged, _Optional_payload&& __other)
266 : : _M_engaged(__engaged)
267 : {
268 : if (__engaged)
269 : _M_construct(std::move(__other._M_get()));
270 : }
271 :
272 : using _Stored_type = remove_const_t<_Tp>;
273 :
274 : struct _Empty_byte { };
275 :
276 : union {
277 : _Empty_byte _M_empty;
278 : _Stored_type _M_payload;
279 : };
280 : bool _M_engaged;
281 :
282 : // The _M_get operations have _M_engaged as a precondition.
283 : constexpr _Tp&
284 : _M_get() noexcept
285 : { return this->_M_payload; }
286 :
287 : constexpr const _Tp&
288 : _M_get() const noexcept
289 : { return this->_M_payload; }
290 : };
291 :
292 : // Payload for optionals with non-trivial copy assignment.
293 : template <typename _Tp>
294 : struct _Optional_payload<_Tp, true, false, true>
295 : {
296 : constexpr _Optional_payload() noexcept
297 : : _M_empty(), _M_engaged(false) { }
298 :
299 : template<typename... _Args>
300 : constexpr
301 : _Optional_payload(in_place_t, _Args&&... __args)
302 : : _M_payload(std::forward<_Args>(__args)...), _M_engaged(true)
303 : { }
304 :
305 : template<typename _Up, typename... _Args>
306 : constexpr
307 : _Optional_payload(std::initializer_list<_Up> __il,
308 : _Args&&... __args)
309 : : _M_payload(__il, std::forward<_Args>(__args)...),
310 : _M_engaged(true)
311 : { }
312 :
313 : constexpr
314 : _Optional_payload(bool __engaged, const _Optional_payload& __other)
315 : : _M_engaged(__engaged)
316 : {
317 : if (__engaged)
318 : _M_construct(__other._M_get());
319 : }
320 :
321 : constexpr
322 : _Optional_payload(bool __engaged, _Optional_payload&& __other)
323 : : _M_engaged(__engaged)
324 : {
325 : if (__engaged)
326 : _M_construct(std::move(__other._M_get()));
327 : }
328 :
329 : _Optional_payload(const _Optional_payload&) = default;
330 : _Optional_payload(_Optional_payload&&) = default;
331 :
332 : constexpr
333 : _Optional_payload&
334 : operator=(const _Optional_payload& __other)
335 : {
336 : if (this->_M_engaged && __other._M_engaged)
337 : this->_M_get() = __other._M_get();
338 : else
339 : {
340 : if (__other._M_engaged)
341 : this->_M_construct(__other._M_get());
342 : else
343 : this->_M_reset();
344 : }
345 : return *this;
346 : }
347 :
348 : _Optional_payload&
349 : operator=(_Optional_payload&& __other) = default;
350 :
351 : using _Stored_type = remove_const_t<_Tp>;
352 :
353 : struct _Empty_byte { };
354 :
355 : union {
356 : _Empty_byte _M_empty;
357 : _Stored_type _M_payload;
358 : };
359 : bool _M_engaged;
360 :
361 : template<typename... _Args>
362 : void
363 : _M_construct(_Args&&... __args)
364 : noexcept(is_nothrow_constructible<_Stored_type, _Args...>())
365 : {
366 : ::new ((void *) std::__addressof(this->_M_payload))
367 : _Stored_type(std::forward<_Args>(__args)...);
368 : this->_M_engaged = true;
369 : }
370 :
371 : // The _M_get operations have _M_engaged as a precondition.
372 : constexpr _Tp&
373 : _M_get() noexcept
374 : { return this->_M_payload; }
375 :
376 : constexpr const _Tp&
377 : _M_get() const noexcept
378 : { return this->_M_payload; }
379 :
380 : // _M_reset is a 'safe' operation with no precondition.
381 : constexpr
382 : void
383 : _M_reset() noexcept
384 : {
385 : if (this->_M_engaged)
386 : {
387 : this->_M_engaged = false;
388 : this->_M_payload.~_Stored_type();
389 : }
390 : }
391 : };
392 :
393 : // Payload for optionals with non-trivial move assignment.
394 : template <typename _Tp>
395 : struct _Optional_payload<_Tp, true, true, false>
396 : {
397 : constexpr _Optional_payload() noexcept
398 : : _M_empty(), _M_engaged(false) { }
399 :
400 : template<typename... _Args>
401 : constexpr
402 : _Optional_payload(in_place_t, _Args&&... __args)
403 : : _M_payload(std::forward<_Args>(__args)...),
404 : _M_engaged(true)
405 : { }
406 :
407 : template<typename _Up, typename... _Args>
408 : constexpr
409 : _Optional_payload(std::initializer_list<_Up> __il,
410 : _Args&&... __args)
411 : : _M_payload(__il, std::forward<_Args>(__args)...),
412 : _M_engaged(true)
413 : { }
414 :
415 : constexpr
416 : _Optional_payload(bool __engaged, const _Optional_payload& __other)
417 : : _M_engaged(__engaged)
418 : {
419 : if (__engaged)
420 : _M_construct(__other._M_get());
421 : }
422 :
423 : constexpr
424 : _Optional_payload(bool __engaged, _Optional_payload&& __other)
425 : : _M_engaged(__engaged)
426 : {
427 : if (__engaged)
428 : _M_construct(std::move(__other._M_get()));
429 : }
430 :
431 : _Optional_payload(const _Optional_payload&) = default;
432 : _Optional_payload(_Optional_payload&&) = default;
433 :
434 : _Optional_payload&
435 : operator=(const _Optional_payload& __other) = default;
436 :
437 : constexpr
438 : _Optional_payload&
439 : operator=(_Optional_payload&& __other)
440 : noexcept(__and_<is_nothrow_move_constructible<_Tp>,
441 : is_nothrow_move_assignable<_Tp>>())
442 : {
443 : if (this->_M_engaged && __other._M_engaged)
444 : this->_M_get() = std::move(__other._M_get());
445 : else
446 : {
447 : if (__other._M_engaged)
448 : this->_M_construct(std::move(__other._M_get()));
449 : else
450 : this->_M_reset();
451 : }
452 : return *this;
453 : }
454 :
455 : using _Stored_type = remove_const_t<_Tp>;
456 :
457 : struct _Empty_byte { };
458 :
459 : union {
460 : _Empty_byte _M_empty;
461 : _Stored_type _M_payload;
462 : };
463 : bool _M_engaged;
464 :
465 : template<typename... _Args>
466 : void
467 : _M_construct(_Args&&... __args)
468 : noexcept(is_nothrow_constructible<_Stored_type, _Args...>())
469 : {
470 : ::new ((void *) std::__addressof(this->_M_payload))
471 : _Stored_type(std::forward<_Args>(__args)...);
472 : this->_M_engaged = true;
473 : }
474 :
475 : // The _M_get operations have _M_engaged as a precondition.
476 : constexpr _Tp&
477 : _M_get() noexcept
478 : { return this->_M_payload; }
479 :
480 : constexpr const _Tp&
481 : _M_get() const noexcept
482 : { return this->_M_payload; }
483 :
484 : // _M_reset is a 'safe' operation with no precondition.
485 : constexpr
486 : void
487 : _M_reset() noexcept
488 : {
489 : if (this->_M_engaged)
490 : {
491 : this->_M_engaged = false;
492 : this->_M_payload.~_Stored_type();
493 : }
494 : }
495 : };
496 :
497 : // Payload for optionals with non-trivial copy and move assignment.
498 : template <typename _Tp>
499 : struct _Optional_payload<_Tp, true, false, false>
500 : {
501 : constexpr _Optional_payload() noexcept
502 : : _M_empty(), _M_engaged(false) {}
503 :
504 : template<typename... _Args>
505 : constexpr
506 : _Optional_payload(in_place_t, _Args&&... __args)
507 : : _M_payload(std::forward<_Args>(__args)...),
508 : _M_engaged(true)
509 : { }
510 :
511 : template<typename _Up, typename... _Args>
512 : constexpr
513 : _Optional_payload(std::initializer_list<_Up> __il,
514 : _Args&&... __args)
515 : : _M_payload(__il, std::forward<_Args>(__args)...),
516 : _M_engaged(true)
517 : { }
518 :
519 : constexpr
520 : _Optional_payload(bool __engaged, const _Optional_payload& __other)
521 : : _M_engaged(__engaged)
522 : {
523 : if (__engaged)
524 : _M_construct(__other._M_get());
525 : }
526 :
527 : constexpr
528 : _Optional_payload(bool __engaged, _Optional_payload&& __other)
529 : : _M_engaged(__engaged)
530 : {
531 : if (__engaged)
532 : _M_construct(std::move(__other._M_get()));
533 : }
534 :
535 : _Optional_payload(const _Optional_payload&) = default;
536 : _Optional_payload(_Optional_payload&&) = default;
537 :
538 : constexpr
539 : _Optional_payload&
540 : operator=(const _Optional_payload& __other)
541 : {
542 : if (this->_M_engaged && __other._M_engaged)
543 : this->_M_get() = __other._M_get();
544 : else
545 : {
546 : if (__other._M_engaged)
547 : this->_M_construct(__other._M_get());
548 : else
549 : this->_M_reset();
550 : }
551 : return *this;
552 : }
553 :
554 : constexpr
555 : _Optional_payload&
556 : operator=(_Optional_payload&& __other)
557 : noexcept(__and_<is_nothrow_move_constructible<_Tp>,
558 : is_nothrow_move_assignable<_Tp>>())
559 : {
560 : if (this->_M_engaged && __other._M_engaged)
561 : this->_M_get() = std::move(__other._M_get());
562 : else
563 : {
564 : if (__other._M_engaged)
565 : this->_M_construct(std::move(__other._M_get()));
566 : else
567 : this->_M_reset();
568 : }
569 : return *this;
570 : }
571 :
572 : using _Stored_type = remove_const_t<_Tp>;
573 :
574 : struct _Empty_byte { };
575 :
576 : union {
577 : _Empty_byte _M_empty;
578 : _Stored_type _M_payload;
579 : };
580 : bool _M_engaged;
581 :
582 : template<typename... _Args>
583 : void
584 : _M_construct(_Args&&... __args)
585 : noexcept(is_nothrow_constructible<_Stored_type, _Args...>())
586 : {
587 : ::new ((void *) std::__addressof(this->_M_payload))
588 : _Stored_type(std::forward<_Args>(__args)...);
589 : this->_M_engaged = true;
590 : }
591 :
592 : // The _M_get operations have _M_engaged as a precondition.
593 : constexpr _Tp&
594 : _M_get() noexcept
595 : { return this->_M_payload; }
596 :
597 : constexpr const _Tp&
598 : _M_get() const noexcept
599 : { return this->_M_payload; }
600 :
601 : // _M_reset is a 'safe' operation with no precondition.
602 : constexpr
603 : void
604 : _M_reset() noexcept
605 : {
606 : if (this->_M_engaged)
607 : {
608 : this->_M_engaged = false;
609 : this->_M_payload.~_Stored_type();
610 : }
611 : }
612 : };
613 :
614 : template<typename _Tp, typename _Dp>
615 : class _Optional_base_impl
616 : {
617 : protected:
618 : using _Stored_type = remove_const_t<_Tp>;
619 :
620 : // The _M_construct operation has !_M_engaged as a precondition
621 : // while _M_destruct has _M_engaged as a precondition.
622 : template<typename... _Args>
623 : void
624 : _M_construct(_Args&&... __args)
625 : noexcept(is_nothrow_constructible<_Stored_type, _Args...>())
626 : {
627 : ::new
628 : (std::__addressof(static_cast<_Dp*>(this)->_M_payload._M_payload))
629 : _Stored_type(std::forward<_Args>(__args)...);
630 : static_cast<_Dp*>(this)->_M_payload._M_engaged = true;
631 : }
632 :
633 : void
634 : _M_destruct() noexcept
635 : {
636 : static_cast<_Dp*>(this)->_M_payload._M_engaged = false;
637 : static_cast<_Dp*>(this)->_M_payload._M_payload.~_Stored_type();
638 : }
639 :
640 : // _M_reset is a 'safe' operation with no precondition.
641 : constexpr
642 : void
643 : _M_reset() noexcept
644 : {
645 : if (static_cast<_Dp*>(this)->_M_payload._M_engaged)
646 : static_cast<_Dp*>(this)->_M_destruct();
647 : }
648 : };
649 :
650 : /**
651 : * @brief Class template that takes care of copy/move constructors
652 : of optional
653 : *
654 : * Such a separate base class template is necessary in order to
655 : * conditionally make copy/move constructors trivial.
656 : * @see optional, _Enable_special_members
657 : */
658 : template<typename _Tp,
659 : bool = is_trivially_copy_constructible_v<_Tp>,
660 : bool = is_trivially_move_constructible_v<_Tp>>
661 : class _Optional_base
662 : // protected inheritance because optional needs to reach that base too
663 : : protected _Optional_base_impl<_Tp, _Optional_base<_Tp>>
664 : {
665 : friend class _Optional_base_impl<_Tp, _Optional_base<_Tp>>;
666 :
667 : public:
668 : // Constructors for disengaged optionals.
669 : constexpr _Optional_base() = default;
670 :
671 : // Constructors for engaged optionals.
672 : template<typename... _Args,
673 : enable_if_t<is_constructible_v<_Tp, _Args&&...>, bool> = false>
674 176 : constexpr explicit _Optional_base(in_place_t, _Args&&... __args)
675 : : _M_payload(in_place,
676 176 : std::forward<_Args>(__args)...) { }
677 :
678 : template<typename _Up, typename... _Args,
679 : enable_if_t<is_constructible_v<_Tp,
680 : initializer_list<_Up>&,
681 : _Args&&...>, bool> = false>
682 : constexpr explicit _Optional_base(in_place_t,
683 : initializer_list<_Up> __il,
684 : _Args&&... __args)
685 : : _M_payload(in_place,
686 : __il, std::forward<_Args>(__args)...)
687 : { }
688 :
689 : // Copy and move constructors.
690 : constexpr _Optional_base(const _Optional_base& __other)
691 : : _M_payload(__other._M_payload._M_engaged,
692 : __other._M_payload)
693 : { }
694 :
695 : constexpr _Optional_base(_Optional_base&& __other)
696 : noexcept(is_nothrow_move_constructible<_Tp>())
697 : : _M_payload(__other._M_payload._M_engaged,
698 : std::move(__other._M_payload))
699 : { }
700 :
701 : // Assignment operators.
702 : _Optional_base& operator=(const _Optional_base&) = default;
703 : _Optional_base& operator=(_Optional_base&&) = default;
704 :
705 : protected:
706 :
707 : constexpr bool _M_is_engaged() const noexcept
708 : { return this->_M_payload._M_engaged; }
709 :
710 : // The _M_get operations have _M_engaged as a precondition.
711 : constexpr _Tp&
712 0 : _M_get() noexcept
713 : {
714 : __glibcxx_assert(this->_M_is_engaged());
715 0 : return this->_M_payload._M_payload;
716 : }
717 :
718 : constexpr const _Tp&
719 : _M_get() const noexcept
720 : {
721 : __glibcxx_assert(this->_M_is_engaged());
722 : return this->_M_payload._M_payload;
723 : }
724 :
725 : private:
726 : _Optional_payload<_Tp> _M_payload;
727 : };
728 :
729 : template<typename _Tp>
730 : class _Optional_base<_Tp, false, true>
731 : : protected _Optional_base_impl<_Tp, _Optional_base<_Tp>>
732 : {
733 : friend class _Optional_base_impl<_Tp, _Optional_base<_Tp>>;
734 : public:
735 :
736 : // Constructors for disengaged optionals.
737 : constexpr _Optional_base() = default;
738 :
739 : // Constructors for engaged optionals.
740 : template<typename... _Args,
741 : enable_if_t<is_constructible_v<_Tp, _Args&&...>, bool> = false>
742 : constexpr explicit _Optional_base(in_place_t, _Args&&... __args)
743 : : _M_payload(in_place,
744 : std::forward<_Args>(__args)...) { }
745 :
746 : template<typename _Up, typename... _Args,
747 : enable_if_t<is_constructible_v<_Tp,
748 : initializer_list<_Up>&,
749 : _Args&&...>, bool> = false>
750 : constexpr explicit _Optional_base(in_place_t,
751 : initializer_list<_Up> __il,
752 : _Args&&... __args)
753 : : _M_payload(in_place,
754 : __il, std::forward<_Args>(__args)...)
755 : { }
756 :
757 : // Copy and move constructors.
758 : constexpr _Optional_base(const _Optional_base& __other)
759 : : _M_payload(__other._M_payload._M_engaged,
760 : __other._M_payload)
761 : { }
762 :
763 : constexpr _Optional_base(_Optional_base&& __other) = default;
764 :
765 : // Assignment operators.
766 : _Optional_base& operator=(const _Optional_base&) = default;
767 : _Optional_base& operator=(_Optional_base&&) = default;
768 :
769 : protected:
770 :
771 : constexpr bool _M_is_engaged() const noexcept
772 : { return this->_M_payload._M_engaged; }
773 :
774 : // The _M_get operations have _M_engaged as a precondition.
775 : constexpr _Tp&
776 : _M_get() noexcept
777 : {
778 : __glibcxx_assert(this->_M_is_engaged());
779 : return this->_M_payload._M_payload;
780 : }
781 :
782 : constexpr const _Tp&
783 : _M_get() const noexcept
784 : {
785 : __glibcxx_assert(this->_M_is_engaged());
786 : return this->_M_payload._M_payload;
787 : }
788 :
789 : private:
790 : _Optional_payload<_Tp> _M_payload;
791 : };
792 :
793 : template<typename _Tp>
794 : class _Optional_base<_Tp, true, false>
795 : : protected _Optional_base_impl<_Tp, _Optional_base<_Tp>>
796 : {
797 : friend class _Optional_base_impl<_Tp, _Optional_base<_Tp>>;
798 : public:
799 :
800 : // Constructors for disengaged optionals.
801 : constexpr _Optional_base() = default;
802 :
803 : // Constructors for engaged optionals.
804 : template<typename... _Args,
805 : enable_if_t<is_constructible_v<_Tp, _Args&&...>, bool> = false>
806 : constexpr explicit _Optional_base(in_place_t, _Args&&... __args)
807 : : _M_payload(in_place,
808 : std::forward<_Args>(__args)...) { }
809 :
810 : template<typename _Up, typename... _Args,
811 : enable_if_t<is_constructible_v<_Tp,
812 : initializer_list<_Up>&,
813 : _Args&&...>, bool> = false>
814 : constexpr explicit _Optional_base(in_place_t,
815 : initializer_list<_Up> __il,
816 : _Args&&... __args)
817 : : _M_payload(in_place,
818 : __il, std::forward<_Args>(__args)...)
819 : { }
820 :
821 : // Copy and move constructors.
822 : constexpr _Optional_base(const _Optional_base& __other) = default;
823 :
824 : constexpr _Optional_base(_Optional_base&& __other)
825 : noexcept(is_nothrow_move_constructible<_Tp>())
826 : : _M_payload(__other._M_payload._M_engaged,
827 : std::move(__other._M_payload))
828 : { }
829 :
830 : // Assignment operators.
831 : _Optional_base& operator=(const _Optional_base&) = default;
832 : _Optional_base& operator=(_Optional_base&&) = default;
833 :
834 : protected:
835 :
836 : constexpr bool _M_is_engaged() const noexcept
837 : { return this->_M_payload._M_engaged; }
838 :
839 : // The _M_get operations have _M_engaged as a precondition.
840 : constexpr _Tp&
841 : _M_get() noexcept
842 : {
843 : __glibcxx_assert(this->_M_is_engaged());
844 : return this->_M_payload._M_payload;
845 : }
846 :
847 : constexpr const _Tp&
848 : _M_get() const noexcept
849 : {
850 : __glibcxx_assert(this->_M_is_engaged());
851 : return this->_M_payload._M_payload;
852 : }
853 :
854 : private:
855 : _Optional_payload<_Tp> _M_payload;
856 : };
857 :
858 : template<typename _Tp>
859 : class _Optional_base<_Tp, true, true>
860 : : protected _Optional_base_impl<_Tp, _Optional_base<_Tp>>
861 : {
862 : friend class _Optional_base_impl<_Tp, _Optional_base<_Tp>>;
863 : public:
864 :
865 : // Constructors for disengaged optionals.
866 : constexpr _Optional_base() = default;
867 :
868 : // Constructors for engaged optionals.
869 : template<typename... _Args,
870 : enable_if_t<is_constructible_v<_Tp, _Args&&...>, bool> = false>
871 : constexpr explicit _Optional_base(in_place_t, _Args&&... __args)
872 : : _M_payload(in_place,
873 : std::forward<_Args>(__args)...) { }
874 :
875 : template<typename _Up, typename... _Args,
876 : enable_if_t<is_constructible_v<_Tp,
877 : initializer_list<_Up>&,
878 : _Args&&...>, bool> = false>
879 : constexpr explicit _Optional_base(in_place_t,
880 : initializer_list<_Up> __il,
881 : _Args&&... __args)
882 : : _M_payload(in_place,
883 : __il, std::forward<_Args>(__args)...)
884 : { }
885 :
886 : // Copy and move constructors.
887 : constexpr _Optional_base(const _Optional_base& __other) = default;
888 : constexpr _Optional_base(_Optional_base&& __other) = default;
889 :
890 : // Assignment operators.
891 : _Optional_base& operator=(const _Optional_base&) = default;
892 : _Optional_base& operator=(_Optional_base&&) = default;
893 :
894 : protected:
895 :
896 : constexpr bool _M_is_engaged() const noexcept
897 : { return this->_M_payload._M_engaged; }
898 :
899 : // The _M_get operations have _M_engaged as a precondition.
900 : constexpr _Tp&
901 : _M_get() noexcept
902 : {
903 : __glibcxx_assert(this->_M_is_engaged());
904 : return this->_M_payload._M_payload;
905 : }
906 :
907 : constexpr const _Tp&
908 : _M_get() const noexcept
909 : {
910 : __glibcxx_assert(this->_M_is_engaged());
911 : return this->_M_payload._M_payload;
912 : }
913 :
914 : private:
915 : _Optional_payload<_Tp> _M_payload;
916 : };
917 :
918 : template<typename _Tp>
919 : class optional;
920 :
921 : template<typename _Tp, typename _Up>
922 : using __converts_from_optional =
923 : __or_<is_constructible<_Tp, const optional<_Up>&>,
924 : is_constructible<_Tp, optional<_Up>&>,
925 : is_constructible<_Tp, const optional<_Up>&&>,
926 : is_constructible<_Tp, optional<_Up>&&>,
927 : is_convertible<const optional<_Up>&, _Tp>,
928 : is_convertible<optional<_Up>&, _Tp>,
929 : is_convertible<const optional<_Up>&&, _Tp>,
930 : is_convertible<optional<_Up>&&, _Tp>>;
931 :
932 : template<typename _Tp, typename _Up>
933 : using __assigns_from_optional =
934 : __or_<is_assignable<_Tp&, const optional<_Up>&>,
935 : is_assignable<_Tp&, optional<_Up>&>,
936 : is_assignable<_Tp&, const optional<_Up>&&>,
937 : is_assignable<_Tp&, optional<_Up>&&>>;
938 :
939 : /**
940 : * @brief Class template for optional values.
941 : */
942 : template<typename _Tp>
943 : class optional
944 : : private _Optional_base<_Tp>,
945 : private _Enable_copy_move<
946 : // Copy constructor.
947 : is_copy_constructible<_Tp>::value,
948 : // Copy assignment.
949 : __and_<is_copy_constructible<_Tp>, is_copy_assignable<_Tp>>::value,
950 : // Move constructor.
951 : is_move_constructible<_Tp>::value,
952 : // Move assignment.
953 : __and_<is_move_constructible<_Tp>, is_move_assignable<_Tp>>::value,
954 : // Unique tag type.
955 : optional<_Tp>>
956 : {
957 : static_assert(!is_same_v<remove_cv_t<_Tp>, nullopt_t>);
958 : static_assert(!is_same_v<remove_cv_t<_Tp>, in_place_t>);
959 : static_assert(!is_reference_v<_Tp>);
960 :
961 : private:
962 : using _Base = _Optional_base<_Tp>;
963 :
964 : public:
965 : using value_type = _Tp;
966 :
967 : constexpr optional() = default;
968 :
969 : constexpr optional(nullopt_t) noexcept { }
970 :
971 : // Converting constructors for engaged optionals.
972 : template <typename _Up = _Tp,
973 : enable_if_t<__and_<
974 : __not_<is_same<optional<_Tp>, decay_t<_Up>>>,
975 : __not_<is_same<in_place_t, decay_t<_Up>>>,
976 : is_constructible<_Tp, _Up&&>,
977 : is_convertible<_Up&&, _Tp>
978 : >::value, bool> = true>
979 176 : constexpr optional(_Up&& __t)
980 176 : : _Base(std::in_place, std::forward<_Up>(__t)) { }
981 :
982 : template <typename _Up = _Tp,
983 : enable_if_t<__and_<
984 : __not_<is_same<optional<_Tp>, decay_t<_Up>>>,
985 : __not_<is_same<in_place_t, decay_t<_Up>>>,
986 : is_constructible<_Tp, _Up&&>,
987 : __not_<is_convertible<_Up&&, _Tp>>
988 : >::value, bool> = false>
989 : explicit constexpr optional(_Up&& __t)
990 : : _Base(std::in_place, std::forward<_Up>(__t)) { }
991 :
992 : template <typename _Up,
993 : enable_if_t<__and_<
994 : __not_<is_same<_Tp, _Up>>,
995 : is_constructible<_Tp, const _Up&>,
996 : is_convertible<const _Up&, _Tp>,
997 : __not_<__converts_from_optional<_Tp, _Up>>
998 : >::value, bool> = true>
999 : constexpr optional(const optional<_Up>& __t)
1000 : {
1001 : if (__t)
1002 : emplace(*__t);
1003 : }
1004 :
1005 : template <typename _Up,
1006 : enable_if_t<__and_<
1007 : __not_<is_same<_Tp, _Up>>,
1008 : is_constructible<_Tp, const _Up&>,
1009 : __not_<is_convertible<const _Up&, _Tp>>,
1010 : __not_<__converts_from_optional<_Tp, _Up>>
1011 : >::value, bool> = false>
1012 : explicit constexpr optional(const optional<_Up>& __t)
1013 : {
1014 : if (__t)
1015 : emplace(*__t);
1016 : }
1017 :
1018 : template <typename _Up,
1019 : enable_if_t<__and_<
1020 : __not_<is_same<_Tp, _Up>>,
1021 : is_constructible<_Tp, _Up&&>,
1022 : is_convertible<_Up&&, _Tp>,
1023 : __not_<__converts_from_optional<_Tp, _Up>>
1024 : >::value, bool> = true>
1025 : constexpr optional(optional<_Up>&& __t)
1026 : {
1027 : if (__t)
1028 : emplace(std::move(*__t));
1029 : }
1030 :
1031 : template <typename _Up,
1032 : enable_if_t<__and_<
1033 : __not_<is_same<_Tp, _Up>>,
1034 : is_constructible<_Tp, _Up&&>,
1035 : __not_<is_convertible<_Up&&, _Tp>>,
1036 : __not_<__converts_from_optional<_Tp, _Up>>
1037 : >::value, bool> = false>
1038 : explicit constexpr optional(optional<_Up>&& __t)
1039 : {
1040 : if (__t)
1041 : emplace(std::move(*__t));
1042 : }
1043 :
1044 : template<typename... _Args,
1045 : enable_if_t<is_constructible_v<_Tp, _Args&&...>, bool> = false>
1046 : explicit constexpr optional(in_place_t, _Args&&... __args)
1047 : : _Base(std::in_place, std::forward<_Args>(__args)...) { }
1048 :
1049 : template<typename _Up, typename... _Args,
1050 : enable_if_t<is_constructible_v<_Tp,
1051 : initializer_list<_Up>&,
1052 : _Args&&...>, bool> = false>
1053 : explicit constexpr optional(in_place_t,
1054 : initializer_list<_Up> __il,
1055 : _Args&&... __args)
1056 : : _Base(std::in_place, __il, std::forward<_Args>(__args)...) { }
1057 :
1058 : // Assignment operators.
1059 : optional&
1060 : operator=(nullopt_t) noexcept
1061 : {
1062 : this->_M_reset();
1063 : return *this;
1064 : }
1065 :
1066 : template<typename _Up = _Tp>
1067 : enable_if_t<__and_<
1068 : __not_<is_same<optional<_Tp>, decay_t<_Up>>>,
1069 : is_constructible<_Tp, _Up>,
1070 : __not_<__and_<is_scalar<_Tp>,
1071 : is_same<_Tp, decay_t<_Up>>>>,
1072 : is_assignable<_Tp&, _Up>>::value,
1073 : optional&>
1074 : operator=(_Up&& __u)
1075 : {
1076 : if (this->_M_is_engaged())
1077 : this->_M_get() = std::forward<_Up>(__u);
1078 : else
1079 : this->_M_construct(std::forward<_Up>(__u));
1080 :
1081 : return *this;
1082 : }
1083 :
1084 : template<typename _Up>
1085 : enable_if_t<__and_<
1086 : __not_<is_same<_Tp, _Up>>,
1087 : is_constructible<_Tp, const _Up&>,
1088 : is_assignable<_Tp&, _Up>,
1089 : __not_<__converts_from_optional<_Tp, _Up>>,
1090 : __not_<__assigns_from_optional<_Tp, _Up>>
1091 : >::value,
1092 : optional&>
1093 : operator=(const optional<_Up>& __u)
1094 : {
1095 : if (__u)
1096 : {
1097 : if (this->_M_is_engaged())
1098 : this->_M_get() = *__u;
1099 : else
1100 : this->_M_construct(*__u);
1101 : }
1102 : else
1103 : {
1104 : this->_M_reset();
1105 : }
1106 : return *this;
1107 : }
1108 :
1109 : template<typename _Up>
1110 : enable_if_t<__and_<
1111 : __not_<is_same<_Tp, _Up>>,
1112 : is_constructible<_Tp, _Up>,
1113 : is_assignable<_Tp&, _Up>,
1114 : __not_<__converts_from_optional<_Tp, _Up>>,
1115 : __not_<__assigns_from_optional<_Tp, _Up>>
1116 : >::value,
1117 : optional&>
1118 : operator=(optional<_Up>&& __u)
1119 : {
1120 : if (__u)
1121 : {
1122 : if (this->_M_is_engaged())
1123 : this->_M_get() = std::move(*__u);
1124 : else
1125 : this->_M_construct(std::move(*__u));
1126 : }
1127 : else
1128 : {
1129 : this->_M_reset();
1130 : }
1131 :
1132 : return *this;
1133 : }
1134 :
1135 : template<typename... _Args>
1136 : enable_if_t<is_constructible<_Tp, _Args&&...>::value, _Tp&>
1137 : emplace(_Args&&... __args)
1138 : {
1139 : this->_M_reset();
1140 : this->_M_construct(std::forward<_Args>(__args)...);
1141 : return this->_M_get();
1142 : }
1143 :
1144 : template<typename _Up, typename... _Args>
1145 : enable_if_t<is_constructible<_Tp, initializer_list<_Up>&,
1146 : _Args&&...>::value, _Tp&>
1147 : emplace(initializer_list<_Up> __il, _Args&&... __args)
1148 : {
1149 : this->_M_reset();
1150 : this->_M_construct(__il, std::forward<_Args>(__args)...);
1151 : return this->_M_get();
1152 : }
1153 :
1154 : // Destructor is implicit, implemented in _Optional_base.
1155 :
1156 : // Swap.
1157 : void
1158 : swap(optional& __other)
1159 : noexcept(is_nothrow_move_constructible<_Tp>()
1160 : && is_nothrow_swappable_v<_Tp>)
1161 : {
1162 : using std::swap;
1163 :
1164 : if (this->_M_is_engaged() && __other._M_is_engaged())
1165 : swap(this->_M_get(), __other._M_get());
1166 : else if (this->_M_is_engaged())
1167 : {
1168 : __other._M_construct(std::move(this->_M_get()));
1169 : this->_M_destruct();
1170 : }
1171 : else if (__other._M_is_engaged())
1172 : {
1173 : this->_M_construct(std::move(__other._M_get()));
1174 : __other._M_destruct();
1175 : }
1176 : }
1177 :
1178 : // Observers.
1179 : constexpr const _Tp*
1180 : operator->() const
1181 : { return std::__addressof(this->_M_get()); }
1182 :
1183 : constexpr
1184 : _Tp*
1185 : operator->()
1186 : { return std::__addressof(this->_M_get()); }
1187 :
1188 : constexpr const _Tp&
1189 : operator*() const&
1190 : { return this->_M_get(); }
1191 :
1192 : constexpr _Tp&
1193 0 : operator*()&
1194 0 : { return this->_M_get(); }
1195 :
1196 : constexpr _Tp&&
1197 : operator*()&&
1198 : { return std::move(this->_M_get()); }
1199 :
1200 : constexpr const _Tp&&
1201 : operator*() const&&
1202 : { return std::move(this->_M_get()); }
1203 :
1204 : constexpr explicit operator bool() const noexcept
1205 : { return this->_M_is_engaged(); }
1206 :
1207 : constexpr bool has_value() const noexcept
1208 : { return this->_M_is_engaged(); }
1209 :
1210 : constexpr const _Tp&
1211 : value() const&
1212 : {
1213 : return this->_M_is_engaged()
1214 : ? this->_M_get()
1215 : : (__throw_bad_optional_access(),
1216 : this->_M_get());
1217 : }
1218 :
1219 : constexpr _Tp&
1220 : value()&
1221 : {
1222 : return this->_M_is_engaged()
1223 : ? this->_M_get()
1224 : : (__throw_bad_optional_access(),
1225 : this->_M_get());
1226 : }
1227 :
1228 : constexpr _Tp&&
1229 : value()&&
1230 : {
1231 : return this->_M_is_engaged()
1232 : ? std::move(this->_M_get())
1233 : : (__throw_bad_optional_access(),
1234 : std::move(this->_M_get()));
1235 : }
1236 :
1237 : constexpr const _Tp&&
1238 : value() const&&
1239 : {
1240 : return this->_M_is_engaged()
1241 : ? std::move(this->_M_get())
1242 : : (__throw_bad_optional_access(),
1243 : std::move(this->_M_get()));
1244 : }
1245 :
1246 : template<typename _Up>
1247 : constexpr _Tp
1248 : value_or(_Up&& __u) const&
1249 : {
1250 : static_assert(is_copy_constructible_v<_Tp>);
1251 : static_assert(is_convertible_v<_Up&&, _Tp>);
1252 :
1253 : return this->_M_is_engaged()
1254 : ? this->_M_get()
1255 : : static_cast<_Tp>(std::forward<_Up>(__u));
1256 : }
1257 :
1258 : template<typename _Up>
1259 : constexpr _Tp
1260 : value_or(_Up&& __u) &&
1261 : {
1262 : static_assert(is_move_constructible_v<_Tp>);
1263 : static_assert(is_convertible_v<_Up&&, _Tp>);
1264 :
1265 : return this->_M_is_engaged()
1266 : ? std::move(this->_M_get())
1267 : : static_cast<_Tp>(std::forward<_Up>(__u));
1268 : }
1269 : void reset() noexcept { this->_M_reset(); }
1270 : };
1271 :
1272 : template<typename _Tp>
1273 : using __optional_relop_t =
1274 : enable_if_t<is_convertible<_Tp, bool>::value, bool>;
1275 :
1276 : // Comparisons between optional values.
1277 : template<typename _Tp, typename _Up>
1278 : constexpr auto
1279 : operator==(const optional<_Tp>& __lhs, const optional<_Up>& __rhs)
1280 : -> __optional_relop_t<decltype(declval<_Tp>() == declval<_Up>())>
1281 : {
1282 : return static_cast<bool>(__lhs) == static_cast<bool>(__rhs)
1283 : && (!__lhs || *__lhs == *__rhs);
1284 : }
1285 :
1286 : template<typename _Tp, typename _Up>
1287 : constexpr auto
1288 : operator!=(const optional<_Tp>& __lhs, const optional<_Up>& __rhs)
1289 : -> __optional_relop_t<decltype(declval<_Tp>() != declval<_Up>())>
1290 : {
1291 : return static_cast<bool>(__lhs) != static_cast<bool>(__rhs)
1292 : || (static_cast<bool>(__lhs) && *__lhs != *__rhs);
1293 : }
1294 :
1295 : template<typename _Tp, typename _Up>
1296 : constexpr auto
1297 : operator<(const optional<_Tp>& __lhs, const optional<_Up>& __rhs)
1298 : -> __optional_relop_t<decltype(declval<_Tp>() < declval<_Up>())>
1299 : {
1300 : return static_cast<bool>(__rhs) && (!__lhs || *__lhs < *__rhs);
1301 : }
1302 :
1303 : template<typename _Tp, typename _Up>
1304 : constexpr auto
1305 : operator>(const optional<_Tp>& __lhs, const optional<_Up>& __rhs)
1306 : -> __optional_relop_t<decltype(declval<_Tp>() > declval<_Up>())>
1307 : {
1308 : return static_cast<bool>(__lhs) && (!__rhs || *__lhs > *__rhs);
1309 : }
1310 :
1311 : template<typename _Tp, typename _Up>
1312 : constexpr auto
1313 : operator<=(const optional<_Tp>& __lhs, const optional<_Up>& __rhs)
1314 : -> __optional_relop_t<decltype(declval<_Tp>() <= declval<_Up>())>
1315 : {
1316 : return !__lhs || (static_cast<bool>(__rhs) && *__lhs <= *__rhs);
1317 : }
1318 :
1319 : template<typename _Tp, typename _Up>
1320 : constexpr auto
1321 : operator>=(const optional<_Tp>& __lhs, const optional<_Up>& __rhs)
1322 : -> __optional_relop_t<decltype(declval<_Tp>() >= declval<_Up>())>
1323 : {
1324 : return !__rhs || (static_cast<bool>(__lhs) && *__lhs >= *__rhs);
1325 : }
1326 :
1327 : // Comparisons with nullopt.
1328 : template<typename _Tp>
1329 : constexpr bool
1330 : operator==(const optional<_Tp>& __lhs, nullopt_t) noexcept
1331 : { return !__lhs; }
1332 :
1333 : template<typename _Tp>
1334 : constexpr bool
1335 : operator==(nullopt_t, const optional<_Tp>& __rhs) noexcept
1336 : { return !__rhs; }
1337 :
1338 : template<typename _Tp>
1339 : constexpr bool
1340 : operator!=(const optional<_Tp>& __lhs, nullopt_t) noexcept
1341 : { return static_cast<bool>(__lhs); }
1342 :
1343 : template<typename _Tp>
1344 : constexpr bool
1345 : operator!=(nullopt_t, const optional<_Tp>& __rhs) noexcept
1346 : { return static_cast<bool>(__rhs); }
1347 :
1348 : template<typename _Tp>
1349 : constexpr bool
1350 : operator<(const optional<_Tp>& /* __lhs */, nullopt_t) noexcept
1351 : { return false; }
1352 :
1353 : template<typename _Tp>
1354 : constexpr bool
1355 : operator<(nullopt_t, const optional<_Tp>& __rhs) noexcept
1356 : { return static_cast<bool>(__rhs); }
1357 :
1358 : template<typename _Tp>
1359 : constexpr bool
1360 : operator>(const optional<_Tp>& __lhs, nullopt_t) noexcept
1361 : { return static_cast<bool>(__lhs); }
1362 :
1363 : template<typename _Tp>
1364 : constexpr bool
1365 : operator>(nullopt_t, const optional<_Tp>& /* __rhs */) noexcept
1366 : { return false; }
1367 :
1368 : template<typename _Tp>
1369 : constexpr bool
1370 : operator<=(const optional<_Tp>& __lhs, nullopt_t) noexcept
1371 : { return !__lhs; }
1372 :
1373 : template<typename _Tp>
1374 : constexpr bool
1375 : operator<=(nullopt_t, const optional<_Tp>& /* __rhs */) noexcept
1376 : { return true; }
1377 :
1378 : template<typename _Tp>
1379 : constexpr bool
1380 : operator>=(const optional<_Tp>& /* __lhs */, nullopt_t) noexcept
1381 : { return true; }
1382 :
1383 : template<typename _Tp>
1384 : constexpr bool
1385 : operator>=(nullopt_t, const optional<_Tp>& __rhs) noexcept
1386 : { return !__rhs; }
1387 :
1388 : // Comparisons with value type.
1389 : template<typename _Tp, typename _Up>
1390 : constexpr auto
1391 : operator==(const optional<_Tp>& __lhs, const _Up& __rhs)
1392 : -> __optional_relop_t<decltype(declval<_Tp>() == declval<_Up>())>
1393 : { return __lhs && *__lhs == __rhs; }
1394 :
1395 : template<typename _Tp, typename _Up>
1396 : constexpr auto
1397 : operator==(const _Up& __lhs, const optional<_Tp>& __rhs)
1398 : -> __optional_relop_t<decltype(declval<_Up>() == declval<_Tp>())>
1399 : { return __rhs && __lhs == *__rhs; }
1400 :
1401 : template<typename _Tp, typename _Up>
1402 : constexpr auto
1403 : operator!=(const optional<_Tp>& __lhs, const _Up& __rhs)
1404 : -> __optional_relop_t<decltype(declval<_Tp>() != declval<_Up>())>
1405 : { return !__lhs || *__lhs != __rhs; }
1406 :
1407 : template<typename _Tp, typename _Up>
1408 : constexpr auto
1409 : operator!=(const _Up& __lhs, const optional<_Tp>& __rhs)
1410 : -> __optional_relop_t<decltype(declval<_Up>() != declval<_Tp>())>
1411 : { return !__rhs || __lhs != *__rhs; }
1412 :
1413 : template<typename _Tp, typename _Up>
1414 : constexpr auto
1415 : operator<(const optional<_Tp>& __lhs, const _Up& __rhs)
1416 : -> __optional_relop_t<decltype(declval<_Tp>() < declval<_Up>())>
1417 : { return !__lhs || *__lhs < __rhs; }
1418 :
1419 : template<typename _Tp, typename _Up>
1420 : constexpr auto
1421 : operator<(const _Up& __lhs, const optional<_Tp>& __rhs)
1422 : -> __optional_relop_t<decltype(declval<_Up>() < declval<_Tp>())>
1423 : { return __rhs && __lhs < *__rhs; }
1424 :
1425 : template<typename _Tp, typename _Up>
1426 : constexpr auto
1427 : operator>(const optional<_Tp>& __lhs, const _Up& __rhs)
1428 : -> __optional_relop_t<decltype(declval<_Tp>() > declval<_Up>())>
1429 : { return __lhs && *__lhs > __rhs; }
1430 :
1431 : template<typename _Tp, typename _Up>
1432 : constexpr auto
1433 : operator>(const _Up& __lhs, const optional<_Tp>& __rhs)
1434 : -> __optional_relop_t<decltype(declval<_Up>() > declval<_Tp>())>
1435 : { return !__rhs || __lhs > *__rhs; }
1436 :
1437 : template<typename _Tp, typename _Up>
1438 : constexpr auto
1439 : operator<=(const optional<_Tp>& __lhs, const _Up& __rhs)
1440 : -> __optional_relop_t<decltype(declval<_Tp>() <= declval<_Up>())>
1441 : { return !__lhs || *__lhs <= __rhs; }
1442 :
1443 : template<typename _Tp, typename _Up>
1444 : constexpr auto
1445 : operator<=(const _Up& __lhs, const optional<_Tp>& __rhs)
1446 : -> __optional_relop_t<decltype(declval<_Up>() <= declval<_Tp>())>
1447 : { return __rhs && __lhs <= *__rhs; }
1448 :
1449 : template<typename _Tp, typename _Up>
1450 : constexpr auto
1451 : operator>=(const optional<_Tp>& __lhs, const _Up& __rhs)
1452 : -> __optional_relop_t<decltype(declval<_Tp>() >= declval<_Up>())>
1453 : { return __lhs && *__lhs >= __rhs; }
1454 :
1455 : template<typename _Tp, typename _Up>
1456 : constexpr auto
1457 : operator>=(const _Up& __lhs, const optional<_Tp>& __rhs)
1458 : -> __optional_relop_t<decltype(declval<_Up>() >= declval<_Tp>())>
1459 : { return !__rhs || __lhs >= *__rhs; }
1460 :
1461 : // Swap and creation functions.
1462 :
1463 : // _GLIBCXX_RESOLVE_LIB_DEFECTS
1464 : // 2748. swappable traits for optionals
1465 : template<typename _Tp>
1466 : inline enable_if_t<is_move_constructible_v<_Tp> && is_swappable_v<_Tp>>
1467 : swap(optional<_Tp>& __lhs, optional<_Tp>& __rhs)
1468 : noexcept(noexcept(__lhs.swap(__rhs)))
1469 : { __lhs.swap(__rhs); }
1470 :
1471 : template<typename _Tp>
1472 : enable_if_t<!(is_move_constructible_v<_Tp> && is_swappable_v<_Tp>)>
1473 : swap(optional<_Tp>&, optional<_Tp>&) = delete;
1474 :
1475 : template<typename _Tp>
1476 : constexpr optional<decay_t<_Tp>>
1477 : make_optional(_Tp&& __t)
1478 : { return optional<decay_t<_Tp>> { std::forward<_Tp>(__t) }; }
1479 :
1480 : template<typename _Tp, typename ..._Args>
1481 : constexpr optional<_Tp>
1482 : make_optional(_Args&&... __args)
1483 : { return optional<_Tp> { in_place, std::forward<_Args>(__args)... }; }
1484 :
1485 : template<typename _Tp, typename _Up, typename ..._Args>
1486 : constexpr optional<_Tp>
1487 : make_optional(initializer_list<_Up> __il, _Args&&... __args)
1488 : { return optional<_Tp> { in_place, __il, std::forward<_Args>(__args)... }; }
1489 :
1490 : // Hash.
1491 :
1492 : template<typename _Tp, typename _Up = remove_const_t<_Tp>,
1493 : bool = __poison_hash<_Up>::__enable_hash_call>
1494 : struct __optional_hash_call_base
1495 : {
1496 : size_t
1497 : operator()(const optional<_Tp>& __t) const
1498 : noexcept(noexcept(hash<_Up>{}(*__t)))
1499 : {
1500 : // We pick an arbitrary hash for disengaged optionals which hopefully
1501 : // usual values of _Tp won't typically hash to.
1502 : constexpr size_t __magic_disengaged_hash = static_cast<size_t>(-3333);
1503 : return __t ? hash<_Up>{}(*__t) : __magic_disengaged_hash;
1504 : }
1505 : };
1506 :
1507 : template<typename _Tp, typename _Up>
1508 : struct __optional_hash_call_base<_Tp, _Up, false> {};
1509 :
1510 : template<typename _Tp>
1511 : struct hash<optional<_Tp>>
1512 : : private __poison_hash<remove_const_t<_Tp>>,
1513 : public __optional_hash_call_base<_Tp>
1514 : {
1515 : using result_type [[__deprecated__]] = size_t;
1516 : using argument_type [[__deprecated__]] = optional<_Tp>;
1517 : };
1518 :
1519 : template<typename _Tp>
1520 : struct __is_fast_hash<hash<optional<_Tp>>> : __is_fast_hash<hash<_Tp>>
1521 : { };
1522 :
1523 : /// @}
1524 :
1525 : #if __cpp_deduction_guides >= 201606
1526 : template <typename _Tp> optional(_Tp) -> optional<_Tp>;
1527 : #endif
1528 :
1529 : _GLIBCXX_END_NAMESPACE_VERSION
1530 : } // namespace std
1531 :
1532 : #endif // C++17
1533 :
1534 : #endif // _GLIBCXX_OPTIONAL
|