blob: 35a4d74c2e86a34a43c51e5b5a5b1df6618699fb [file] [log] [blame]
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001// -*- C++ -*-
2//===-------------------------- optional ----------------------------------===//
3//
4// The LLVM Compiler Infrastructure
5//
6// This file is dual licensed under the MIT and the University of Illinois Open
7// Source Licenses. See LICENSE.TXT for details.
8//
9//===----------------------------------------------------------------------===//
10
11#ifndef _LIBCPP_OPTIONAL
12#define _LIBCPP_OPTIONAL
13
14/*
15 optional synopsis
16
17// C++1z
18
19namespace std {
Casey Carter84b8a402017-04-17 20:15:16 +000020 // 23.6.3, optional for object types
Eric Fiselierd4ec6352016-10-12 07:46:20 +000021 template <class T> class optional;
22
Casey Carter84b8a402017-04-17 20:15:16 +000023 // 23.6.4, no-value state indicator
Eric Fiselierd4ec6352016-10-12 07:46:20 +000024 struct nullopt_t{see below };
25 constexpr nullopt_t nullopt(unspecified );
26
Casey Carter84b8a402017-04-17 20:15:16 +000027 // 23.6.5, class bad_optional_access
Eric Fiselierd4ec6352016-10-12 07:46:20 +000028 class bad_optional_access;
29
Casey Carter84b8a402017-04-17 20:15:16 +000030 // 23.6.6, relational operators
31 template <class T, class U>
32 constexpr bool operator==(const optional<T>&, const optional<U>&);
33 template <class T, class U>
34 constexpr bool operator!=(const optional<T>&, const optional<U>&);
35 template <class T, class U>
36 constexpr bool operator<(const optional<T>&, const optional<U>&);
37 template <class T, class U>
38 constexpr bool operator>(const optional<T>&, const optional<U>&);
39 template <class T, class U>
40 constexpr bool operator<=(const optional<T>&, const optional<U>&);
41 template <class T, class U>
42 constexpr bool operator>=(const optional<T>&, const optional<U>&);
43
44 // 23.6.7 comparison with nullopt
Eric Fiselierd4ec6352016-10-12 07:46:20 +000045 template <class T> constexpr bool operator==(const optional<T>&, nullopt_t) noexcept;
46 template <class T> constexpr bool operator==(nullopt_t, const optional<T>&) noexcept;
47 template <class T> constexpr bool operator!=(const optional<T>&, nullopt_t) noexcept;
48 template <class T> constexpr bool operator!=(nullopt_t, const optional<T>&) noexcept;
49 template <class T> constexpr bool operator<(const optional<T>&, nullopt_t) noexcept;
50 template <class T> constexpr bool operator<(nullopt_t, const optional<T>&) noexcept;
51 template <class T> constexpr bool operator<=(const optional<T>&, nullopt_t) noexcept;
52 template <class T> constexpr bool operator<=(nullopt_t, const optional<T>&) noexcept;
53 template <class T> constexpr bool operator>(const optional<T>&, nullopt_t) noexcept;
54 template <class T> constexpr bool operator>(nullopt_t, const optional<T>&) noexcept;
55 template <class T> constexpr bool operator>=(const optional<T>&, nullopt_t) noexcept;
56 template <class T> constexpr bool operator>=(nullopt_t, const optional<T>&) noexcept;
57
Casey Carter84b8a402017-04-17 20:15:16 +000058 // 23.6.8, comparison with T
59 template <class T, class U> constexpr bool operator==(const optional<T>&, const U&);
Marshall Clow29dd7e42017-11-01 01:27:25 +000060 template <class T, class U> constexpr bool operator==(const T&, const optional<U>&);
Casey Carter84b8a402017-04-17 20:15:16 +000061 template <class T, class U> constexpr bool operator!=(const optional<T>&, const U&);
Marshall Clow29dd7e42017-11-01 01:27:25 +000062 template <class T, class U> constexpr bool operator!=(const T&, const optional<U>&);
Casey Carter84b8a402017-04-17 20:15:16 +000063 template <class T, class U> constexpr bool operator<(const optional<T>&, const U&);
Marshall Clow29dd7e42017-11-01 01:27:25 +000064 template <class T, class U> constexpr bool operator<(const T&, const optional<U>&);
Casey Carter84b8a402017-04-17 20:15:16 +000065 template <class T, class U> constexpr bool operator<=(const optional<T>&, const U&);
Marshall Clow29dd7e42017-11-01 01:27:25 +000066 template <class T, class U> constexpr bool operator<=(const T&, const optional<U>&);
Casey Carter84b8a402017-04-17 20:15:16 +000067 template <class T, class U> constexpr bool operator>(const optional<T>&, const U&);
Marshall Clow29dd7e42017-11-01 01:27:25 +000068 template <class T, class U> constexpr bool operator>(const T&, const optional<U>&);
Casey Carter84b8a402017-04-17 20:15:16 +000069 template <class T, class U> constexpr bool operator>=(const optional<T>&, const U&);
Marshall Clow29dd7e42017-11-01 01:27:25 +000070 template <class T, class U> constexpr bool operator>=(const T&, const optional<U>&);
Eric Fiselierd4ec6352016-10-12 07:46:20 +000071
Casey Carter84b8a402017-04-17 20:15:16 +000072 // 23.6.9, specialized algorithms
Eric Fiselierd4ec6352016-10-12 07:46:20 +000073 template <class T> void swap(optional<T>&, optional<T>&) noexcept(see below );
74 template <class T> constexpr optional<see below > make_optional(T&&);
75 template <class T, class... Args>
76 constexpr optional<T> make_optional(Args&&... args);
77 template <class T, class U, class... Args>
78 constexpr optional<T> make_optional(initializer_list<U> il, Args&&... args);
79
Casey Carter84b8a402017-04-17 20:15:16 +000080 // 23.6.10, hash support
Eric Fiselierd4ec6352016-10-12 07:46:20 +000081 template <class T> struct hash;
82 template <class T> struct hash<optional<T>>;
83
84 template <class T> class optional {
85 public:
86 using value_type = T;
87
Casey Carter84b8a402017-04-17 20:15:16 +000088 // 23.6.3.1, constructors
Eric Fiselierd4ec6352016-10-12 07:46:20 +000089 constexpr optional() noexcept;
90 constexpr optional(nullopt_t) noexcept;
91 optional(const optional &);
Marshall Clow45ff9822017-04-12 22:51:27 +000092 optional(optional &&) noexcept(see below);
Eric Fiselierd4ec6352016-10-12 07:46:20 +000093 template <class... Args> constexpr explicit optional(in_place_t, Args &&...);
94 template <class U, class... Args>
95 constexpr explicit optional(in_place_t, initializer_list<U>, Args &&...);
96 template <class U = T>
97 constexpr EXPLICIT optional(U &&);
98 template <class U>
99 constexpr EXPLICIT optional(const optional<U> &);
100 template <class U>
101 constexpr EXPLICIT optional(optional<U> &&);
102
Casey Carter84b8a402017-04-17 20:15:16 +0000103 // 23.6.3.2, destructor
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000104 ~optional();
105
Casey Carter84b8a402017-04-17 20:15:16 +0000106 // 23.6.3.3, assignment
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000107 optional &operator=(nullopt_t) noexcept;
108 optional &operator=(const optional &);
109 optional &operator=(optional &&) noexcept(see below );
110 template <class U = T> optional &operator=(U &&);
111 template <class U> optional &operator=(const optional<U> &);
112 template <class U> optional &operator=(optional<U> &&);
Marshall Clow45ff9822017-04-12 22:51:27 +0000113 template <class... Args> T& emplace(Args &&...);
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000114 template <class U, class... Args>
Marshall Clow45ff9822017-04-12 22:51:27 +0000115 T& emplace(initializer_list<U>, Args &&...);
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000116
Casey Carter84b8a402017-04-17 20:15:16 +0000117 // 23.6.3.4, swap
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000118 void swap(optional &) noexcept(see below );
119
Casey Carter84b8a402017-04-17 20:15:16 +0000120 // 23.6.3.5, observers
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000121 constexpr T const *operator->() const;
122 constexpr T *operator->();
123 constexpr T const &operator*() const &;
124 constexpr T &operator*() &;
125 constexpr T &&operator*() &&;
126 constexpr const T &&operator*() const &&;
127 constexpr explicit operator bool() const noexcept;
128 constexpr bool has_value() const noexcept;
129 constexpr T const &value() const &;
130 constexpr T &value() &;
131 constexpr T &&value() &&;
132 constexpr const T &&value() const &&;
133 template <class U> constexpr T value_or(U &&) const &;
134 template <class U> constexpr T value_or(U &&) &&;
135
Casey Carter84b8a402017-04-17 20:15:16 +0000136 // 23.6.3.6, modifiers
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000137 void reset() noexcept;
138
139 private:
140 T *val; // exposition only
141 };
142} // namespace std
143
144*/
145
146#include <__config>
147#include <__debug>
148#include <__functional_base>
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000149#include <functional>
150#include <initializer_list>
151#include <new>
152#include <stdexcept>
153#include <type_traits>
154#include <utility>
155
156#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
157#pragma GCC system_header
158#endif
159
Eric Fiselierf4433a32017-05-31 22:07:49 +0000160_LIBCPP_PUSH_MACROS
161#include <__undef_macros>
162
163
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000164namespace std // purposefully not using versioning namespace
165{
166
167class _LIBCPP_EXCEPTION_ABI bad_optional_access
Marshall Clowa627d4a2017-02-05 20:06:38 +0000168 : public exception
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000169{
170public:
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000171 // Get the key function ~bad_optional_access() into the dylib
Marshall Clow53fc0372017-02-05 20:52:32 +0000172 virtual ~bad_optional_access() _NOEXCEPT;
Marshall Clowa627d4a2017-02-05 20:06:38 +0000173 virtual const char* what() const _NOEXCEPT;
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000174};
175
176} // std
177
178#if _LIBCPP_STD_VER > 14
179
180_LIBCPP_BEGIN_NAMESPACE_STD
181
182_LIBCPP_NORETURN
183inline _LIBCPP_INLINE_VISIBILITY
184void __throw_bad_optional_access() {
185#ifndef _LIBCPP_NO_EXCEPTIONS
186 throw bad_optional_access();
187#else
188 _VSTD::abort();
189#endif
190}
191
192struct nullopt_t
193{
194 struct __secret_tag { _LIBCPP_INLINE_VISIBILITY explicit __secret_tag() = default; };
195 _LIBCPP_INLINE_VISIBILITY constexpr explicit nullopt_t(__secret_tag, __secret_tag) noexcept {}
196};
197
198/* inline */ constexpr nullopt_t nullopt{nullopt_t::__secret_tag{}, nullopt_t::__secret_tag{}};
199
200template <class _Tp, bool = is_trivially_destructible<_Tp>::value>
201struct __optional_destruct_base;
202
203template <class _Tp>
204struct __optional_destruct_base<_Tp, false>
205{
206 typedef _Tp value_type;
207 static_assert(is_object_v<value_type>,
208 "instantiation of optional with a non-object type is undefined behavior");
209 union
210 {
211 char __null_state_;
212 value_type __val_;
213 };
214 bool __engaged_;
215
216 _LIBCPP_INLINE_VISIBILITY
217 ~__optional_destruct_base()
218 {
219 if (__engaged_)
220 __val_.~value_type();
221 }
222
223 _LIBCPP_INLINE_VISIBILITY
224 constexpr __optional_destruct_base() noexcept
225 : __null_state_(),
226 __engaged_(false) {}
227
228 template <class... _Args>
229 _LIBCPP_INLINE_VISIBILITY
230 constexpr explicit __optional_destruct_base(in_place_t, _Args&&... __args)
231 : __val_(_VSTD::forward<_Args>(__args)...),
232 __engaged_(true) {}
233
234 _LIBCPP_INLINE_VISIBILITY
235 void reset() noexcept
236 {
237 if (__engaged_)
238 {
239 __val_.~value_type();
240 __engaged_ = false;
241 }
242 }
243};
244
245template <class _Tp>
246struct __optional_destruct_base<_Tp, true>
247{
248 typedef _Tp value_type;
249 static_assert(is_object_v<value_type>,
250 "instantiation of optional with a non-object type is undefined behavior");
251 union
252 {
253 char __null_state_;
254 value_type __val_;
255 };
256 bool __engaged_;
257
258 _LIBCPP_INLINE_VISIBILITY
259 constexpr __optional_destruct_base() noexcept
260 : __null_state_(),
261 __engaged_(false) {}
262
263 template <class... _Args>
264 _LIBCPP_INLINE_VISIBILITY
265 constexpr explicit __optional_destruct_base(in_place_t, _Args&&... __args)
266 : __val_(_VSTD::forward<_Args>(__args)...),
267 __engaged_(true) {}
268
269 _LIBCPP_INLINE_VISIBILITY
270 void reset() noexcept
271 {
272 if (__engaged_)
273 {
274 __engaged_ = false;
275 }
276 }
277};
278
279template <class _Tp, bool = is_reference<_Tp>::value>
280struct __optional_storage_base : __optional_destruct_base<_Tp>
281{
282 using __base = __optional_destruct_base<_Tp>;
283 using value_type = _Tp;
284 using __base::__base;
285
286 _LIBCPP_INLINE_VISIBILITY
287 constexpr bool has_value() const noexcept
288 {
289 return this->__engaged_;
290 }
291
292 _LIBCPP_INLINE_VISIBILITY
293 constexpr value_type& __get() & noexcept
294 {
295 return this->__val_;
296 }
297 _LIBCPP_INLINE_VISIBILITY
298 constexpr const value_type& __get() const& noexcept
299 {
300 return this->__val_;
301 }
302 _LIBCPP_INLINE_VISIBILITY
303 constexpr value_type&& __get() && noexcept
304 {
305 return _VSTD::move(this->__val_);
306 }
307 _LIBCPP_INLINE_VISIBILITY
308 constexpr const value_type&& __get() const&& noexcept
309 {
310 return _VSTD::move(this->__val_);
311 }
312
313 template <class... _Args>
314 _LIBCPP_INLINE_VISIBILITY
315 void __construct(_Args&&... __args)
316 {
317 _LIBCPP_ASSERT(!has_value(), "__construct called for engaged __optional_storage");
318 ::new((void*)_VSTD::addressof(this->__val_)) value_type(_VSTD::forward<_Args>(__args)...);
319 this->__engaged_ = true;
320 }
321
322 template <class _That>
323 _LIBCPP_INLINE_VISIBILITY
324 void __construct_from(_That&& __opt)
325 {
326 if (__opt.has_value())
327 __construct(_VSTD::forward<_That>(__opt).__get());
328 }
329
330 template <class _That>
331 _LIBCPP_INLINE_VISIBILITY
332 void __assign_from(_That&& __opt)
333 {
334 if (this->__engaged_ == __opt.has_value())
335 {
336 if (this->__engaged_)
337 this->__val_ = _VSTD::forward<_That>(__opt).__get();
338 }
339 else
340 {
341 if (this->__engaged_)
342 this->reset();
343 else
344 __construct(_VSTD::forward<_That>(__opt).__get());
345 }
346 }
347};
348
349// optional<T&> is currently required ill-formed, however it may to be in the
350// future. For this reason it has already been implemented to ensure we can
351// make the change in an ABI compatible manner.
352template <class _Tp>
353struct __optional_storage_base<_Tp, true>
354{
355 using value_type = _Tp;
356 using __raw_type = remove_reference_t<_Tp>;
357 __raw_type* __value_;
358
359 template <class _Up>
360 static constexpr bool __can_bind_reference() {
361 using _RawUp = typename remove_reference<_Up>::type;
362 using _UpPtr = _RawUp*;
363 using _RawTp = typename remove_reference<_Tp>::type;
364 using _TpPtr = _RawTp*;
365 using _CheckLValueArg = integral_constant<bool,
366 (is_lvalue_reference<_Up>::value && is_convertible<_UpPtr, _TpPtr>::value)
367 || is_same<_RawUp, reference_wrapper<_RawTp>>::value
368 || is_same<_RawUp, reference_wrapper<typename remove_const<_RawTp>::type>>::value
369 >;
370 return (is_lvalue_reference<_Tp>::value && _CheckLValueArg::value)
371 || (is_rvalue_reference<_Tp>::value && !is_lvalue_reference<_Up>::value &&
372 is_convertible<_UpPtr, _TpPtr>::value);
373 }
374
375 _LIBCPP_INLINE_VISIBILITY
376 constexpr __optional_storage_base() noexcept
377 : __value_(nullptr) {}
378
379 template <class _UArg>
380 _LIBCPP_INLINE_VISIBILITY
381 constexpr explicit __optional_storage_base(in_place_t, _UArg&& __uarg)
382 : __value_(_VSTD::addressof(__uarg))
383 {
384 static_assert(__can_bind_reference<_UArg>(),
385 "Attempted to construct a reference element in tuple from a "
386 "possible temporary");
387 }
388
389 _LIBCPP_INLINE_VISIBILITY
390 void reset() noexcept { __value_ = nullptr; }
391
392 _LIBCPP_INLINE_VISIBILITY
393 constexpr bool has_value() const noexcept
394 { return __value_ != nullptr; }
395
396 _LIBCPP_INLINE_VISIBILITY
397 constexpr value_type& __get() const& noexcept
398 { return *__value_; }
399
400 _LIBCPP_INLINE_VISIBILITY
401 constexpr value_type&& __get() const&& noexcept
402 { return _VSTD::forward<value_type>(*__value_); }
403
404 template <class _UArg>
405 _LIBCPP_INLINE_VISIBILITY
406 void __construct(_UArg&& __val)
407 {
408 _LIBCPP_ASSERT(!has_value(), "__construct called for engaged __optional_storage");
409 static_assert(__can_bind_reference<_UArg>(),
410 "Attempted to construct a reference element in tuple from a "
411 "possible temporary");
412 __value_ = _VSTD::addressof(__val);
413 }
414
415 template <class _That>
416 _LIBCPP_INLINE_VISIBILITY
417 void __construct_from(_That&& __opt)
418 {
419 if (__opt.has_value())
420 __construct(_VSTD::forward<_That>(__opt).__get());
421 }
422
423 template <class _That>
424 _LIBCPP_INLINE_VISIBILITY
425 void __assign_from(_That&& __opt)
426 {
427 if (has_value() == __opt.has_value())
428 {
429 if (has_value())
430 *__value_ = _VSTD::forward<_That>(__opt).__get();
431 }
432 else
433 {
434 if (has_value())
435 reset();
436 else
437 __construct(_VSTD::forward<_That>(__opt).__get());
438 }
439 }
440};
441
Casey Carterc189f7f2017-07-09 17:15:49 +0000442template <class _Tp, bool = is_trivially_copy_constructible<_Tp>::value>
443struct __optional_copy_base : __optional_storage_base<_Tp>
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000444{
445 using __optional_storage_base<_Tp>::__optional_storage_base;
446};
447
448template <class _Tp>
Casey Carterc189f7f2017-07-09 17:15:49 +0000449struct __optional_copy_base<_Tp, false> : __optional_storage_base<_Tp>
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000450{
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000451 using __optional_storage_base<_Tp>::__optional_storage_base;
452
453 _LIBCPP_INLINE_VISIBILITY
Casey Carterc189f7f2017-07-09 17:15:49 +0000454 __optional_copy_base() = default;
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000455
456 _LIBCPP_INLINE_VISIBILITY
Casey Carterc189f7f2017-07-09 17:15:49 +0000457 __optional_copy_base(const __optional_copy_base& __opt)
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000458 {
459 this->__construct_from(__opt);
460 }
461
462 _LIBCPP_INLINE_VISIBILITY
Casey Carterc189f7f2017-07-09 17:15:49 +0000463 __optional_copy_base(__optional_copy_base&&) = default;
464 _LIBCPP_INLINE_VISIBILITY
465 __optional_copy_base& operator=(const __optional_copy_base&) = default;
466 _LIBCPP_INLINE_VISIBILITY
467 __optional_copy_base& operator=(__optional_copy_base&&) = default;
468};
469
470template <class _Tp, bool = is_trivially_move_constructible<_Tp>::value>
471struct __optional_move_base : __optional_copy_base<_Tp>
472{
473 using __optional_copy_base<_Tp>::__optional_copy_base;
474};
475
476template <class _Tp>
477struct __optional_move_base<_Tp, false> : __optional_copy_base<_Tp>
478{
479 using value_type = _Tp;
480 using __optional_copy_base<_Tp>::__optional_copy_base;
481
482 _LIBCPP_INLINE_VISIBILITY
483 __optional_move_base() = default;
484 _LIBCPP_INLINE_VISIBILITY
485 __optional_move_base(const __optional_move_base&) = default;
486
487 _LIBCPP_INLINE_VISIBILITY
488 __optional_move_base(__optional_move_base&& __opt)
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000489 noexcept(is_nothrow_move_constructible_v<value_type>)
490 {
491 this->__construct_from(_VSTD::move(__opt));
492 }
493
494 _LIBCPP_INLINE_VISIBILITY
Casey Carterc189f7f2017-07-09 17:15:49 +0000495 __optional_move_base& operator=(const __optional_move_base&) = default;
496 _LIBCPP_INLINE_VISIBILITY
497 __optional_move_base& operator=(__optional_move_base&&) = default;
498};
499
500template <class _Tp, bool =
501 is_trivially_destructible<_Tp>::value &&
502 is_trivially_copy_constructible<_Tp>::value &&
503 is_trivially_copy_assignable<_Tp>::value>
504struct __optional_copy_assign_base : __optional_move_base<_Tp>
505{
506 using __optional_move_base<_Tp>::__optional_move_base;
507};
508
509template <class _Tp>
510struct __optional_copy_assign_base<_Tp, false> : __optional_move_base<_Tp>
511{
512 using __optional_move_base<_Tp>::__optional_move_base;
513
514 _LIBCPP_INLINE_VISIBILITY
515 __optional_copy_assign_base() = default;
516 _LIBCPP_INLINE_VISIBILITY
517 __optional_copy_assign_base(const __optional_copy_assign_base&) = default;
518 _LIBCPP_INLINE_VISIBILITY
519 __optional_copy_assign_base(__optional_copy_assign_base&&) = default;
520
521 _LIBCPP_INLINE_VISIBILITY
522 __optional_copy_assign_base& operator=(const __optional_copy_assign_base& __opt)
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000523 {
524 this->__assign_from(__opt);
525 return *this;
526 }
527
528 _LIBCPP_INLINE_VISIBILITY
Casey Carterc189f7f2017-07-09 17:15:49 +0000529 __optional_copy_assign_base& operator=(__optional_copy_assign_base&&) = default;
530};
531
532template <class _Tp, bool =
533 is_trivially_destructible<_Tp>::value &&
534 is_trivially_move_constructible<_Tp>::value &&
535 is_trivially_move_assignable<_Tp>::value>
536struct __optional_move_assign_base : __optional_copy_assign_base<_Tp>
537{
538 using __optional_copy_assign_base<_Tp>::__optional_copy_assign_base;
539};
540
541template <class _Tp>
542struct __optional_move_assign_base<_Tp, false> : __optional_copy_assign_base<_Tp>
543{
544 using value_type = _Tp;
545 using __optional_copy_assign_base<_Tp>::__optional_copy_assign_base;
546
547 _LIBCPP_INLINE_VISIBILITY
548 __optional_move_assign_base() = default;
549 _LIBCPP_INLINE_VISIBILITY
550 __optional_move_assign_base(const __optional_move_assign_base& __opt) = default;
551 _LIBCPP_INLINE_VISIBILITY
552 __optional_move_assign_base(__optional_move_assign_base&&) = default;
553 _LIBCPP_INLINE_VISIBILITY
554 __optional_move_assign_base& operator=(const __optional_move_assign_base&) = default;
555
556 _LIBCPP_INLINE_VISIBILITY
557 __optional_move_assign_base& operator=(__optional_move_assign_base&& __opt)
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000558 noexcept(is_nothrow_move_assignable_v<value_type> &&
559 is_nothrow_move_constructible_v<value_type>)
560 {
561 this->__assign_from(_VSTD::move(__opt));
562 return *this;
563 }
564};
565
566template <class _Tp>
567using __optional_sfinae_ctor_base_t = __sfinae_ctor_base<
568 is_copy_constructible<_Tp>::value,
569 is_move_constructible<_Tp>::value
570>;
571
572template <class _Tp>
573using __optional_sfinae_assign_base_t = __sfinae_assign_base<
574 (is_copy_constructible<_Tp>::value && is_copy_assignable<_Tp>::value),
575 (is_move_constructible<_Tp>::value && is_move_assignable<_Tp>::value)
576>;
577
578template <class _Tp>
579class optional
Casey Carterc189f7f2017-07-09 17:15:49 +0000580 : private __optional_move_assign_base<_Tp>
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000581 , private __optional_sfinae_ctor_base_t<_Tp>
582 , private __optional_sfinae_assign_base_t<_Tp>
583{
Casey Carterc189f7f2017-07-09 17:15:49 +0000584 using __base = __optional_move_assign_base<_Tp>;
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000585public:
586 using value_type = _Tp;
587
588private:
589 // Disable the reference extension using this static assert.
590 static_assert(!is_same_v<value_type, in_place_t>,
591 "instantiation of optional with in_place_t is ill-formed");
592 static_assert(!is_same_v<__uncvref_t<value_type>, nullopt_t>,
593 "instantiation of optional with nullopt_t is ill-formed");
594 static_assert(!is_reference_v<value_type>,
595 "instantiation of optional with a reference type is ill-formed");
596 static_assert(is_destructible_v<value_type>,
597 "instantiation of optional with a non-destructible type is ill-formed");
598
599 // LWG2756: conditionally explicit conversion from _Up
600 struct _CheckOptionalArgsConstructor {
601 template <class _Up>
602 static constexpr bool __enable_implicit() {
603 return is_constructible_v<_Tp, _Up&&> &&
604 is_convertible_v<_Up&&, _Tp>;
605 }
606
607 template <class _Up>
608 static constexpr bool __enable_explicit() {
609 return is_constructible_v<_Tp, _Up&&> &&
610 !is_convertible_v<_Up&&, _Tp>;
611 }
612 };
613 template <class _Up>
614 using _CheckOptionalArgsCtor = conditional_t<
Eric Fiselierf7b1d302017-03-30 19:43:50 +0000615 !is_same_v<decay_t<_Up>, in_place_t> &&
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000616 !is_same_v<decay_t<_Up>, optional>,
617 _CheckOptionalArgsConstructor,
618 __check_tuple_constructor_fail
619 >;
620 template <class _QualUp>
621 struct _CheckOptionalLikeConstructor {
622 template <class _Up, class _Opt = optional<_Up>>
623 using __check_constructible_from_opt = __lazy_or<
624 is_constructible<_Tp, _Opt&>,
625 is_constructible<_Tp, _Opt const&>,
626 is_constructible<_Tp, _Opt&&>,
627 is_constructible<_Tp, _Opt const&&>,
628 is_convertible<_Opt&, _Tp>,
629 is_convertible<_Opt const&, _Tp>,
630 is_convertible<_Opt&&, _Tp>,
631 is_convertible<_Opt const&&, _Tp>
632 >;
633 template <class _Up, class _Opt = optional<_Up>>
634 using __check_assignable_from_opt = __lazy_or<
635 is_assignable<_Tp&, _Opt&>,
636 is_assignable<_Tp&, _Opt const&>,
637 is_assignable<_Tp&, _Opt&&>,
638 is_assignable<_Tp&, _Opt const&&>
639 >;
640 template <class _Up, class _QUp = _QualUp>
641 static constexpr bool __enable_implicit() {
642 return is_convertible<_QUp, _Tp>::value &&
643 !__check_constructible_from_opt<_Up>::value;
644 }
645 template <class _Up, class _QUp = _QualUp>
646 static constexpr bool __enable_explicit() {
647 return !is_convertible<_QUp, _Tp>::value &&
648 !__check_constructible_from_opt<_Up>::value;
649 }
650 template <class _Up, class _QUp = _QualUp>
651 static constexpr bool __enable_assign() {
652 // Construction and assignability of _Qup to _Tp has already been
653 // checked.
654 return !__check_constructible_from_opt<_Up>::value &&
655 !__check_assignable_from_opt<_Up>::value;
656 }
657 };
658
659 template <class _Up, class _QualUp>
660 using _CheckOptionalLikeCtor = conditional_t<
661 __lazy_and<
662 __lazy_not<is_same<_Up, _Tp>>,
663 is_constructible<_Tp, _QualUp>
664 >::value,
665 _CheckOptionalLikeConstructor<_QualUp>,
666 __check_tuple_constructor_fail
667 >;
668 template <class _Up, class _QualUp>
669 using _CheckOptionalLikeAssign = conditional_t<
670 __lazy_and<
671 __lazy_not<is_same<_Up, _Tp>>,
672 is_constructible<_Tp, _QualUp>,
673 is_assignable<_Tp&, _QualUp>
674 >::value,
675 _CheckOptionalLikeConstructor<_QualUp>,
676 __check_tuple_constructor_fail
677 >;
678public:
679
680 _LIBCPP_INLINE_VISIBILITY constexpr optional() noexcept {}
Marshall Clowd44e2e32017-05-17 15:30:01 +0000681 _LIBCPP_INLINE_VISIBILITY constexpr optional(const optional&) = default;
682 _LIBCPP_INLINE_VISIBILITY constexpr optional(optional&&) = default;
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000683 _LIBCPP_INLINE_VISIBILITY constexpr optional(nullopt_t) noexcept {}
684
685 template <class... _Args, class = enable_if_t<
686 is_constructible_v<value_type, _Args...>>
687 >
688 _LIBCPP_INLINE_VISIBILITY
689 constexpr explicit optional(in_place_t, _Args&&... __args)
690 : __base(in_place, _VSTD::forward<_Args>(__args)...) {}
691
692 template <class _Up, class... _Args, class = enable_if_t<
693 is_constructible_v<value_type, initializer_list<_Up>&, _Args...>>
694 >
695 _LIBCPP_INLINE_VISIBILITY
696 constexpr explicit optional(in_place_t, initializer_list<_Up> __il, _Args&&... __args)
697 : __base(in_place, __il, _VSTD::forward<_Args>(__args)...) {}
698
699 template <class _Up = value_type, enable_if_t<
700 _CheckOptionalArgsCtor<_Up>::template __enable_implicit<_Up>()
701 , int> = 0>
702 _LIBCPP_INLINE_VISIBILITY
703 constexpr optional(_Up&& __v)
704 : __base(in_place, _VSTD::forward<_Up>(__v)) {}
705
706 template <class _Up, enable_if_t<
707 _CheckOptionalArgsCtor<_Up>::template __enable_explicit<_Up>()
708 , int> = 0>
709 _LIBCPP_INLINE_VISIBILITY
710 constexpr explicit optional(_Up&& __v)
711 : __base(in_place, _VSTD::forward<_Up>(__v)) {}
712
713 // LWG2756: conditionally explicit conversion from const optional<_Up>&
714 template <class _Up, enable_if_t<
715 _CheckOptionalLikeCtor<_Up, _Up const&>::template __enable_implicit<_Up>()
716 , int> = 0>
717 _LIBCPP_INLINE_VISIBILITY
718 optional(const optional<_Up>& __v)
719 {
720 this->__construct_from(__v);
721 }
722 template <class _Up, enable_if_t<
723 _CheckOptionalLikeCtor<_Up, _Up const&>::template __enable_explicit<_Up>()
724 , int> = 0>
725 _LIBCPP_INLINE_VISIBILITY
726 explicit optional(const optional<_Up>& __v)
727 {
728 this->__construct_from(__v);
729 }
730
731 // LWG2756: conditionally explicit conversion from optional<_Up>&&
732 template <class _Up, enable_if_t<
733 _CheckOptionalLikeCtor<_Up, _Up &&>::template __enable_implicit<_Up>()
734 , int> = 0>
735 _LIBCPP_INLINE_VISIBILITY
736 optional(optional<_Up>&& __v)
737 {
738 this->__construct_from(_VSTD::move(__v));
739 }
740 template <class _Up, enable_if_t<
741 _CheckOptionalLikeCtor<_Up, _Up &&>::template __enable_explicit<_Up>()
742 , int> = 0>
743 _LIBCPP_INLINE_VISIBILITY
744 explicit optional(optional<_Up>&& __v)
745 {
746 this->__construct_from(_VSTD::move(__v));
747 }
748
749 _LIBCPP_INLINE_VISIBILITY
750 optional& operator=(nullopt_t) noexcept
751 {
752 reset();
753 return *this;
754 }
755
756 _LIBCPP_INLINE_VISIBILITY optional& operator=(const optional&) = default;
757 _LIBCPP_INLINE_VISIBILITY optional& operator=(optional&&) = default;
758
759 // LWG2756
760 template <class _Up = value_type,
761 class = enable_if_t
Eric Fiselierb9014262016-10-16 03:21:35 +0000762 <__lazy_and<
763 integral_constant<bool,
764 !is_same_v<decay_t<_Up>, optional> &&
765 !(is_same_v<_Up, value_type> && is_scalar_v<value_type>)
766 >,
767 is_constructible<value_type, _Up>,
768 is_assignable<value_type&, _Up>
769 >::value>
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000770 >
771 _LIBCPP_INLINE_VISIBILITY
772 optional&
773 operator=(_Up&& __v)
774 {
775 if (this->has_value())
776 this->__get() = _VSTD::forward<_Up>(__v);
777 else
778 this->__construct(_VSTD::forward<_Up>(__v));
779 return *this;
780 }
781
782 // LWG2756
783 template <class _Up, enable_if_t<
784 _CheckOptionalLikeAssign<_Up, _Up const&>::template __enable_assign<_Up>()
785 , int> = 0>
786 _LIBCPP_INLINE_VISIBILITY
787 optional&
788 operator=(const optional<_Up>& __v)
789 {
790 this->__assign_from(__v);
791 return *this;
792 }
793
794 // LWG2756
795 template <class _Up, enable_if_t<
796 _CheckOptionalLikeCtor<_Up, _Up &&>::template __enable_assign<_Up>()
797 , int> = 0>
798 _LIBCPP_INLINE_VISIBILITY
799 optional&
800 operator=(optional<_Up>&& __v)
801 {
802 this->__assign_from(_VSTD::move(__v));
803 return *this;
804 }
805
806 template <class... _Args,
807 class = enable_if_t
808 <
809 is_constructible_v<value_type, _Args...>
810 >
811 >
812 _LIBCPP_INLINE_VISIBILITY
Marshall Clow45ff9822017-04-12 22:51:27 +0000813 _Tp &
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000814 emplace(_Args&&... __args)
815 {
816 reset();
817 this->__construct(_VSTD::forward<_Args>(__args)...);
Marshall Clow45ff9822017-04-12 22:51:27 +0000818 return this->__get();
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000819 }
820
821 template <class _Up, class... _Args,
822 class = enable_if_t
823 <
824 is_constructible_v<value_type, initializer_list<_Up>&, _Args...>
825 >
826 >
827 _LIBCPP_INLINE_VISIBILITY
Marshall Clow45ff9822017-04-12 22:51:27 +0000828 _Tp &
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000829 emplace(initializer_list<_Up> __il, _Args&&... __args)
830 {
831 reset();
832 this->__construct(__il, _VSTD::forward<_Args>(__args)...);
Marshall Clow45ff9822017-04-12 22:51:27 +0000833 return this->__get();
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000834 }
835
836 _LIBCPP_INLINE_VISIBILITY
837 void swap(optional& __opt)
838 noexcept(is_nothrow_move_constructible_v<value_type> &&
839 is_nothrow_swappable_v<value_type>)
840 {
841 if (this->has_value() == __opt.has_value())
842 {
843 using _VSTD::swap;
844 if (this->has_value())
845 swap(this->__get(), __opt.__get());
846 }
847 else
848 {
849 if (this->has_value())
850 {
851 __opt.__construct(_VSTD::move(this->__get()));
852 reset();
853 }
854 else
855 {
856 this->__construct(_VSTD::move(__opt.__get()));
857 __opt.reset();
858 }
859 }
860 }
861
862 _LIBCPP_INLINE_VISIBILITY
863 constexpr
864 add_pointer_t<value_type const>
865 operator->() const
866 {
867 _LIBCPP_ASSERT(this->has_value(), "optional operator-> called for disengaged value");
868#ifndef _LIBCPP_HAS_NO_BUILTIN_ADDRESSOF
869 return _VSTD::addressof(this->__get());
870#else
871 return __operator_arrow(__has_operator_addressof<value_type>{}, this->__get());
872#endif
873 }
874
875 _LIBCPP_INLINE_VISIBILITY
876 constexpr
877 add_pointer_t<value_type>
878 operator->()
879 {
880 _LIBCPP_ASSERT(this->has_value(), "optional operator-> called for disengaged value");
881#ifndef _LIBCPP_HAS_NO_BUILTIN_ADDRESSOF
882 return _VSTD::addressof(this->__get());
883#else
884 return __operator_arrow(__has_operator_addressof<value_type>{}, this->__get());
885#endif
886 }
887
888 _LIBCPP_INLINE_VISIBILITY
889 constexpr
890 const value_type&
891 operator*() const&
892 {
893 _LIBCPP_ASSERT(this->has_value(), "optional operator* called for disengaged value");
894 return this->__get();
895 }
896
897 _LIBCPP_INLINE_VISIBILITY
898 constexpr
899 value_type&
900 operator*() &
901 {
902 _LIBCPP_ASSERT(this->has_value(), "optional operator* called for disengaged value");
903 return this->__get();
904 }
905
906 _LIBCPP_INLINE_VISIBILITY
907 constexpr
908 value_type&&
909 operator*() &&
910 {
911 _LIBCPP_ASSERT(this->has_value(), "optional operator* called for disengaged value");
912 return _VSTD::move(this->__get());
913 }
914
915 _LIBCPP_INLINE_VISIBILITY
916 constexpr
917 const value_type&&
918 operator*() const&&
919 {
920 _LIBCPP_ASSERT(this->has_value(), "optional operator* called for disengaged value");
921 return _VSTD::move(this->__get());
922 }
923
924 _LIBCPP_INLINE_VISIBILITY
925 constexpr explicit operator bool() const noexcept { return has_value(); }
926
927 using __base::has_value;
928 using __base::__get;
929
930 _LIBCPP_INLINE_VISIBILITY
931 constexpr value_type const& value() const&
932 {
933 if (!this->has_value())
934 __throw_bad_optional_access();
935 return this->__get();
936 }
937
938 _LIBCPP_INLINE_VISIBILITY
939 constexpr value_type& value() &
940 {
941 if (!this->has_value())
942 __throw_bad_optional_access();
943 return this->__get();
944 }
945
946 _LIBCPP_INLINE_VISIBILITY
947 constexpr value_type&& value() &&
948 {
949 if (!this->has_value())
950 __throw_bad_optional_access();
951 return _VSTD::move(this->__get());
952 }
953
954 _LIBCPP_INLINE_VISIBILITY
955 constexpr value_type const&& value() const&&
956 {
957 if (!this->has_value())
958 __throw_bad_optional_access();
959 return _VSTD::move(this->__get());
960 }
961
962 template <class _Up>
963 _LIBCPP_INLINE_VISIBILITY
964 constexpr value_type value_or(_Up&& __v) const&
965 {
966 static_assert(is_copy_constructible_v<value_type>,
967 "optional<T>::value_or: T must be copy constructible");
968 static_assert(is_convertible_v<_Up, value_type>,
969 "optional<T>::value_or: U must be convertible to T");
970 return this->has_value() ? this->__get() :
971 static_cast<value_type>(_VSTD::forward<_Up>(__v));
972 }
973
974 template <class _Up>
975 _LIBCPP_INLINE_VISIBILITY
Casey Cartercb05fae2017-06-06 18:47:26 +0000976 constexpr value_type value_or(_Up&& __v) &&
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000977 {
978 static_assert(is_move_constructible_v<value_type>,
979 "optional<T>::value_or: T must be move constructible");
980 static_assert(is_convertible_v<_Up, value_type>,
981 "optional<T>::value_or: U must be convertible to T");
982 return this->has_value() ? _VSTD::move(this->__get()) :
983 static_cast<value_type>(_VSTD::forward<_Up>(__v));
984 }
985
986 using __base::reset;
987
988private:
989 template <class _Up>
990 _LIBCPP_INLINE_VISIBILITY
991 static _Up*
992 __operator_arrow(true_type, _Up& __x)
993 {
994 return _VSTD::addressof(__x);
995 }
996
997 template <class _Up>
998 _LIBCPP_INLINE_VISIBILITY
999 static constexpr _Up*
1000 __operator_arrow(false_type, _Up& __x)
1001 {
1002 return &__x;
1003 }
1004};
1005
1006// Comparisons between optionals
Eric Fiselier8af90142017-03-30 20:06:52 +00001007template <class _Tp, class _Up>
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001008_LIBCPP_INLINE_VISIBILITY constexpr
1009enable_if_t<
1010 is_convertible_v<decltype(_VSTD::declval<const _Tp&>() ==
Eric Fiselier8af90142017-03-30 20:06:52 +00001011 _VSTD::declval<const _Up&>()), bool>,
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001012 bool
1013>
Eric Fiselier8af90142017-03-30 20:06:52 +00001014operator==(const optional<_Tp>& __x, const optional<_Up>& __y)
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001015{
1016 if (static_cast<bool>(__x) != static_cast<bool>(__y))
1017 return false;
1018 if (!static_cast<bool>(__x))
1019 return true;
1020 return *__x == *__y;
1021}
1022
Eric Fiselier8af90142017-03-30 20:06:52 +00001023template <class _Tp, class _Up>
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001024_LIBCPP_INLINE_VISIBILITY constexpr
1025enable_if_t<
1026 is_convertible_v<decltype(_VSTD::declval<const _Tp&>() !=
Eric Fiselier8af90142017-03-30 20:06:52 +00001027 _VSTD::declval<const _Up&>()), bool>,
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001028 bool
1029>
Eric Fiselier8af90142017-03-30 20:06:52 +00001030operator!=(const optional<_Tp>& __x, const optional<_Up>& __y)
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001031{
1032 if (static_cast<bool>(__x) != static_cast<bool>(__y))
1033 return true;
1034 if (!static_cast<bool>(__x))
1035 return false;
1036 return *__x != *__y;
1037}
1038
Eric Fiselier8af90142017-03-30 20:06:52 +00001039template <class _Tp, class _Up>
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001040_LIBCPP_INLINE_VISIBILITY constexpr
1041enable_if_t<
1042 is_convertible_v<decltype(_VSTD::declval<const _Tp&>() <
Eric Fiselier8af90142017-03-30 20:06:52 +00001043 _VSTD::declval<const _Up&>()), bool>,
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001044 bool
1045>
Eric Fiselier8af90142017-03-30 20:06:52 +00001046operator<(const optional<_Tp>& __x, const optional<_Up>& __y)
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001047{
1048 if (!static_cast<bool>(__y))
1049 return false;
1050 if (!static_cast<bool>(__x))
1051 return true;
1052 return *__x < *__y;
1053}
1054
Eric Fiselier8af90142017-03-30 20:06:52 +00001055template <class _Tp, class _Up>
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001056_LIBCPP_INLINE_VISIBILITY constexpr
1057enable_if_t<
1058 is_convertible_v<decltype(_VSTD::declval<const _Tp&>() >
Eric Fiselier8af90142017-03-30 20:06:52 +00001059 _VSTD::declval<const _Up&>()), bool>,
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001060 bool
1061>
Eric Fiselier8af90142017-03-30 20:06:52 +00001062operator>(const optional<_Tp>& __x, const optional<_Up>& __y)
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001063{
1064 if (!static_cast<bool>(__x))
1065 return false;
1066 if (!static_cast<bool>(__y))
1067 return true;
1068 return *__x > *__y;
1069}
1070
Eric Fiselier8af90142017-03-30 20:06:52 +00001071template <class _Tp, class _Up>
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001072_LIBCPP_INLINE_VISIBILITY constexpr
1073enable_if_t<
1074 is_convertible_v<decltype(_VSTD::declval<const _Tp&>() <=
Eric Fiselier8af90142017-03-30 20:06:52 +00001075 _VSTD::declval<const _Up&>()), bool>,
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001076 bool
1077>
Eric Fiselier8af90142017-03-30 20:06:52 +00001078operator<=(const optional<_Tp>& __x, const optional<_Up>& __y)
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001079{
1080 if (!static_cast<bool>(__x))
1081 return true;
1082 if (!static_cast<bool>(__y))
1083 return false;
1084 return *__x <= *__y;
1085}
1086
Eric Fiselier8af90142017-03-30 20:06:52 +00001087template <class _Tp, class _Up>
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001088_LIBCPP_INLINE_VISIBILITY constexpr
1089enable_if_t<
1090 is_convertible_v<decltype(_VSTD::declval<const _Tp&>() >=
Eric Fiselier8af90142017-03-30 20:06:52 +00001091 _VSTD::declval<const _Up&>()), bool>,
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001092 bool
1093>
Eric Fiselier8af90142017-03-30 20:06:52 +00001094operator>=(const optional<_Tp>& __x, const optional<_Up>& __y)
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001095{
1096 if (!static_cast<bool>(__y))
1097 return true;
1098 if (!static_cast<bool>(__x))
1099 return false;
1100 return *__x >= *__y;
1101}
1102
1103// Comparisons with nullopt
1104template <class _Tp>
1105_LIBCPP_INLINE_VISIBILITY constexpr
1106bool
1107operator==(const optional<_Tp>& __x, nullopt_t) noexcept
1108{
1109 return !static_cast<bool>(__x);
1110}
1111
1112template <class _Tp>
1113_LIBCPP_INLINE_VISIBILITY constexpr
1114bool
1115operator==(nullopt_t, const optional<_Tp>& __x) noexcept
1116{
1117 return !static_cast<bool>(__x);
1118}
1119
1120template <class _Tp>
1121_LIBCPP_INLINE_VISIBILITY constexpr
1122bool
1123operator!=(const optional<_Tp>& __x, nullopt_t) noexcept
1124{
1125 return static_cast<bool>(__x);
1126}
1127
1128template <class _Tp>
1129_LIBCPP_INLINE_VISIBILITY constexpr
1130bool
1131operator!=(nullopt_t, const optional<_Tp>& __x) noexcept
1132{
1133 return static_cast<bool>(__x);
1134}
1135
1136template <class _Tp>
1137_LIBCPP_INLINE_VISIBILITY constexpr
1138bool
1139operator<(const optional<_Tp>&, nullopt_t) noexcept
1140{
1141 return false;
1142}
1143
1144template <class _Tp>
1145_LIBCPP_INLINE_VISIBILITY constexpr
1146bool
1147operator<(nullopt_t, const optional<_Tp>& __x) noexcept
1148{
1149 return static_cast<bool>(__x);
1150}
1151
1152template <class _Tp>
1153_LIBCPP_INLINE_VISIBILITY constexpr
1154bool
1155operator<=(const optional<_Tp>& __x, nullopt_t) noexcept
1156{
1157 return !static_cast<bool>(__x);
1158}
1159
1160template <class _Tp>
1161_LIBCPP_INLINE_VISIBILITY constexpr
1162bool
Eric Fiselier6003c772016-12-23 23:37:52 +00001163operator<=(nullopt_t, const optional<_Tp>&) noexcept
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001164{
1165 return true;
1166}
1167
1168template <class _Tp>
1169_LIBCPP_INLINE_VISIBILITY constexpr
1170bool
1171operator>(const optional<_Tp>& __x, nullopt_t) noexcept
1172{
1173 return static_cast<bool>(__x);
1174}
1175
1176template <class _Tp>
1177_LIBCPP_INLINE_VISIBILITY constexpr
1178bool
Eric Fiselier6003c772016-12-23 23:37:52 +00001179operator>(nullopt_t, const optional<_Tp>&) noexcept
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001180{
1181 return false;
1182}
1183
1184template <class _Tp>
1185_LIBCPP_INLINE_VISIBILITY constexpr
1186bool
1187operator>=(const optional<_Tp>&, nullopt_t) noexcept
1188{
1189 return true;
1190}
1191
1192template <class _Tp>
1193_LIBCPP_INLINE_VISIBILITY constexpr
1194bool
1195operator>=(nullopt_t, const optional<_Tp>& __x) noexcept
1196{
1197 return !static_cast<bool>(__x);
1198}
1199
1200// Comparisons with T
Eric Fiselier8af90142017-03-30 20:06:52 +00001201template <class _Tp, class _Up>
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001202_LIBCPP_INLINE_VISIBILITY constexpr
1203enable_if_t<
1204 is_convertible_v<decltype(_VSTD::declval<const _Tp&>() ==
Eric Fiselier8af90142017-03-30 20:06:52 +00001205 _VSTD::declval<const _Up&>()), bool>,
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001206 bool
1207>
Eric Fiselier8af90142017-03-30 20:06:52 +00001208operator==(const optional<_Tp>& __x, const _Up& __v)
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001209{
1210 return static_cast<bool>(__x) ? *__x == __v : false;
1211}
1212
Eric Fiselier8af90142017-03-30 20:06:52 +00001213template <class _Tp, class _Up>
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001214_LIBCPP_INLINE_VISIBILITY constexpr
1215enable_if_t<
1216 is_convertible_v<decltype(_VSTD::declval<const _Tp&>() ==
Eric Fiselier8af90142017-03-30 20:06:52 +00001217 _VSTD::declval<const _Up&>()), bool>,
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001218 bool
1219>
Eric Fiselier8af90142017-03-30 20:06:52 +00001220operator==(const _Tp& __v, const optional<_Up>& __x)
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001221{
1222 return static_cast<bool>(__x) ? __v == *__x : false;
1223}
1224
Eric Fiselier8af90142017-03-30 20:06:52 +00001225template <class _Tp, class _Up>
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001226_LIBCPP_INLINE_VISIBILITY constexpr
1227enable_if_t<
1228 is_convertible_v<decltype(_VSTD::declval<const _Tp&>() !=
Eric Fiselier8af90142017-03-30 20:06:52 +00001229 _VSTD::declval<const _Up&>()), bool>,
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001230 bool
1231>
Eric Fiselier8af90142017-03-30 20:06:52 +00001232operator!=(const optional<_Tp>& __x, const _Up& __v)
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001233{
1234 return static_cast<bool>(__x) ? *__x != __v : true;
1235}
1236
Eric Fiselier8af90142017-03-30 20:06:52 +00001237template <class _Tp, class _Up>
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001238_LIBCPP_INLINE_VISIBILITY constexpr
1239enable_if_t<
1240 is_convertible_v<decltype(_VSTD::declval<const _Tp&>() !=
Eric Fiselier8af90142017-03-30 20:06:52 +00001241 _VSTD::declval<const _Up&>()), bool>,
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001242 bool
1243>
Eric Fiselier8af90142017-03-30 20:06:52 +00001244operator!=(const _Tp& __v, const optional<_Up>& __x)
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001245{
1246 return static_cast<bool>(__x) ? __v != *__x : true;
1247}
1248
Eric Fiselier8af90142017-03-30 20:06:52 +00001249template <class _Tp, class _Up>
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001250_LIBCPP_INLINE_VISIBILITY constexpr
1251enable_if_t<
1252 is_convertible_v<decltype(_VSTD::declval<const _Tp&>() <
Eric Fiselier8af90142017-03-30 20:06:52 +00001253 _VSTD::declval<const _Up&>()), bool>,
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001254 bool
1255>
Eric Fiselier8af90142017-03-30 20:06:52 +00001256operator<(const optional<_Tp>& __x, const _Up& __v)
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001257{
1258 return static_cast<bool>(__x) ? *__x < __v : true;
1259}
1260
Eric Fiselier8af90142017-03-30 20:06:52 +00001261template <class _Tp, class _Up>
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001262_LIBCPP_INLINE_VISIBILITY constexpr
1263enable_if_t<
1264 is_convertible_v<decltype(_VSTD::declval<const _Tp&>() <
Eric Fiselier8af90142017-03-30 20:06:52 +00001265 _VSTD::declval<const _Up&>()), bool>,
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001266 bool
1267>
Eric Fiselier8af90142017-03-30 20:06:52 +00001268operator<(const _Tp& __v, const optional<_Up>& __x)
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001269{
1270 return static_cast<bool>(__x) ? __v < *__x : false;
1271}
1272
Eric Fiselier8af90142017-03-30 20:06:52 +00001273template <class _Tp, class _Up>
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001274_LIBCPP_INLINE_VISIBILITY constexpr
1275enable_if_t<
1276 is_convertible_v<decltype(_VSTD::declval<const _Tp&>() <=
Eric Fiselier8af90142017-03-30 20:06:52 +00001277 _VSTD::declval<const _Up&>()), bool>,
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001278 bool
1279>
Eric Fiselier8af90142017-03-30 20:06:52 +00001280operator<=(const optional<_Tp>& __x, const _Up& __v)
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001281{
1282 return static_cast<bool>(__x) ? *__x <= __v : true;
1283}
1284
Eric Fiselier8af90142017-03-30 20:06:52 +00001285template <class _Tp, class _Up>
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001286_LIBCPP_INLINE_VISIBILITY constexpr
1287enable_if_t<
1288 is_convertible_v<decltype(_VSTD::declval<const _Tp&>() <=
Eric Fiselier8af90142017-03-30 20:06:52 +00001289 _VSTD::declval<const _Up&>()), bool>,
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001290 bool
1291>
Eric Fiselier8af90142017-03-30 20:06:52 +00001292operator<=(const _Tp& __v, const optional<_Up>& __x)
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001293{
1294 return static_cast<bool>(__x) ? __v <= *__x : false;
1295}
1296
Eric Fiselier8af90142017-03-30 20:06:52 +00001297template <class _Tp, class _Up>
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001298_LIBCPP_INLINE_VISIBILITY constexpr
1299enable_if_t<
1300 is_convertible_v<decltype(_VSTD::declval<const _Tp&>() >
Eric Fiselier8af90142017-03-30 20:06:52 +00001301 _VSTD::declval<const _Up&>()), bool>,
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001302 bool
1303>
Eric Fiselier8af90142017-03-30 20:06:52 +00001304operator>(const optional<_Tp>& __x, const _Up& __v)
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001305{
1306 return static_cast<bool>(__x) ? *__x > __v : false;
1307}
1308
Eric Fiselier8af90142017-03-30 20:06:52 +00001309template <class _Tp, class _Up>
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001310_LIBCPP_INLINE_VISIBILITY constexpr
1311enable_if_t<
1312 is_convertible_v<decltype(_VSTD::declval<const _Tp&>() >
Eric Fiselier8af90142017-03-30 20:06:52 +00001313 _VSTD::declval<const _Up&>()), bool>,
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001314 bool
1315>
Eric Fiselier8af90142017-03-30 20:06:52 +00001316operator>(const _Tp& __v, const optional<_Up>& __x)
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001317{
1318 return static_cast<bool>(__x) ? __v > *__x : true;
1319}
1320
Eric Fiselier8af90142017-03-30 20:06:52 +00001321template <class _Tp, class _Up>
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001322_LIBCPP_INLINE_VISIBILITY constexpr
1323enable_if_t<
1324 is_convertible_v<decltype(_VSTD::declval<const _Tp&>() >=
Eric Fiselier8af90142017-03-30 20:06:52 +00001325 _VSTD::declval<const _Up&>()), bool>,
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001326 bool
1327>
Eric Fiselier8af90142017-03-30 20:06:52 +00001328operator>=(const optional<_Tp>& __x, const _Up& __v)
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001329{
1330 return static_cast<bool>(__x) ? *__x >= __v : false;
1331}
1332
Eric Fiselier8af90142017-03-30 20:06:52 +00001333template <class _Tp, class _Up>
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001334_LIBCPP_INLINE_VISIBILITY constexpr
1335enable_if_t<
1336 is_convertible_v<decltype(_VSTD::declval<const _Tp&>() >=
Eric Fiselier8af90142017-03-30 20:06:52 +00001337 _VSTD::declval<const _Up&>()), bool>,
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001338 bool
1339>
Eric Fiselier8af90142017-03-30 20:06:52 +00001340operator>=(const _Tp& __v, const optional<_Up>& __x)
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001341{
1342 return static_cast<bool>(__x) ? __v >= *__x : true;
1343}
1344
1345
1346template <class _Tp>
1347inline _LIBCPP_INLINE_VISIBILITY
1348enable_if_t<
1349 is_move_constructible_v<_Tp> && is_swappable_v<_Tp>,
1350 void
1351>
1352swap(optional<_Tp>& __x, optional<_Tp>& __y) noexcept(noexcept(__x.swap(__y)))
1353{
1354 __x.swap(__y);
1355}
1356
1357template <class _Tp>
1358_LIBCPP_INLINE_VISIBILITY constexpr
1359optional<decay_t<_Tp>> make_optional(_Tp&& __v)
1360{
1361 return optional<decay_t<_Tp>>(_VSTD::forward<_Tp>(__v));
1362}
1363
1364template <class _Tp, class... _Args>
1365_LIBCPP_INLINE_VISIBILITY constexpr
1366optional<_Tp> make_optional(_Args&&... __args)
1367{
1368 return optional<_Tp>(in_place, _VSTD::forward<_Args>(__args)...);
1369}
1370
1371template <class _Tp, class _Up, class... _Args>
1372_LIBCPP_INLINE_VISIBILITY constexpr
1373optional<_Tp> make_optional(initializer_list<_Up> __il, _Args&&... __args)
1374{
1375 return optional<_Tp>(in_place, __il, _VSTD::forward<_Args>(__args)...);
1376}
1377
1378template <class _Tp>
Eric Fiselier698a97b2017-01-21 00:02:12 +00001379struct _LIBCPP_TEMPLATE_VIS hash<
1380 __enable_hash_helper<optional<_Tp>, remove_const_t<_Tp>>
1381>
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001382{
1383 typedef optional<_Tp> argument_type;
1384 typedef size_t result_type;
1385
1386 _LIBCPP_INLINE_VISIBILITY
Marshall Clow49036892017-03-23 02:40:28 +00001387 result_type operator()(const argument_type& __opt) const
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001388 {
Eric Fiselier698a97b2017-01-21 00:02:12 +00001389 return static_cast<bool>(__opt) ? hash<remove_const_t<_Tp>>()(*__opt) : 0;
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001390 }
1391};
1392
1393_LIBCPP_END_NAMESPACE_STD
1394
1395#endif // _LIBCPP_STD_VER > 14
1396
Eric Fiselierf4433a32017-05-31 22:07:49 +00001397_LIBCPP_POP_MACROS
1398
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001399#endif // _LIBCPP_OPTIONAL