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