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