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 201603 |
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 | _Optional_payload(in_place_t, _Args&&... __args) |
119 | : _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 | ~_Optional_payload() |
198 | { |
199 | if (_M_engaged) |
200 | _M_payload.~_Stored_type(); |
201 | } |
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 | constexpr explicit _Optional_base(in_place_t, _Args&&... __args) |
675 | : _M_payload(in_place, |
676 | 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 | _M_get() noexcept |
713 | { |
714 | __glibcxx_assert(this->_M_is_engaged()); |
715 | 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 | constexpr optional(_Up&& __t) |
980 | : _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 | operator*()& |
1194 | { 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 | _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 |
1535 | |