blob: 9ef0aac39992f841f58ba0dafd401a483d0d8130 [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 };
Marshall Clowf1bf62f2018-01-02 17:17:01 +000025 inline constexpr nullopt_t nullopt(unspecified );
Eric Fiselierd4ec6352016-10-12 07:46:20 +000026
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 };
Marshall Clowe3c71ae2018-05-25 02:08:49 +0000142
143template<class T>
144 optional(T) -> optional<T>;
145
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000146} // namespace std
147
148*/
149
150#include <__config>
151#include <__debug>
152#include <__functional_base>
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000153#include <functional>
154#include <initializer_list>
155#include <new>
156#include <stdexcept>
157#include <type_traits>
158#include <utility>
Marshall Clow0a1e7502018-09-12 19:41:40 +0000159#include <version>
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000160
161#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
162#pragma GCC system_header
163#endif
164
Eric Fiselierf4433a32017-05-31 22:07:49 +0000165_LIBCPP_PUSH_MACROS
166#include <__undef_macros>
167
168
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000169namespace std // purposefully not using versioning namespace
170{
171
172class _LIBCPP_EXCEPTION_ABI bad_optional_access
Marshall Clowa627d4a2017-02-05 20:06:38 +0000173 : public exception
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000174{
175public:
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000176 // Get the key function ~bad_optional_access() into the dylib
Marshall Clow53fc0372017-02-05 20:52:32 +0000177 virtual ~bad_optional_access() _NOEXCEPT;
Marshall Clowa627d4a2017-02-05 20:06:38 +0000178 virtual const char* what() const _NOEXCEPT;
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000179};
180
181} // std
182
183#if _LIBCPP_STD_VER > 14
184
185_LIBCPP_BEGIN_NAMESPACE_STD
186
187_LIBCPP_NORETURN
188inline _LIBCPP_INLINE_VISIBILITY
189void __throw_bad_optional_access() {
190#ifndef _LIBCPP_NO_EXCEPTIONS
191 throw bad_optional_access();
192#else
193 _VSTD::abort();
194#endif
195}
196
197struct nullopt_t
198{
199 struct __secret_tag { _LIBCPP_INLINE_VISIBILITY explicit __secret_tag() = default; };
200 _LIBCPP_INLINE_VISIBILITY constexpr explicit nullopt_t(__secret_tag, __secret_tag) noexcept {}
201};
202
Marshall Clowf1bf62f2018-01-02 17:17:01 +0000203_LIBCPP_INLINE_VAR constexpr nullopt_t nullopt{nullopt_t::__secret_tag{}, nullopt_t::__secret_tag{}};
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000204
205template <class _Tp, bool = is_trivially_destructible<_Tp>::value>
206struct __optional_destruct_base;
207
208template <class _Tp>
209struct __optional_destruct_base<_Tp, false>
210{
211 typedef _Tp value_type;
212 static_assert(is_object_v<value_type>,
213 "instantiation of optional with a non-object type is undefined behavior");
214 union
215 {
216 char __null_state_;
217 value_type __val_;
218 };
219 bool __engaged_;
220
221 _LIBCPP_INLINE_VISIBILITY
222 ~__optional_destruct_base()
223 {
224 if (__engaged_)
225 __val_.~value_type();
226 }
227
228 _LIBCPP_INLINE_VISIBILITY
229 constexpr __optional_destruct_base() noexcept
230 : __null_state_(),
231 __engaged_(false) {}
232
233 template <class... _Args>
234 _LIBCPP_INLINE_VISIBILITY
235 constexpr explicit __optional_destruct_base(in_place_t, _Args&&... __args)
236 : __val_(_VSTD::forward<_Args>(__args)...),
237 __engaged_(true) {}
238
239 _LIBCPP_INLINE_VISIBILITY
240 void reset() noexcept
241 {
242 if (__engaged_)
243 {
244 __val_.~value_type();
245 __engaged_ = false;
246 }
247 }
248};
249
250template <class _Tp>
251struct __optional_destruct_base<_Tp, true>
252{
253 typedef _Tp value_type;
254 static_assert(is_object_v<value_type>,
255 "instantiation of optional with a non-object type is undefined behavior");
256 union
257 {
258 char __null_state_;
259 value_type __val_;
260 };
261 bool __engaged_;
262
263 _LIBCPP_INLINE_VISIBILITY
264 constexpr __optional_destruct_base() noexcept
265 : __null_state_(),
266 __engaged_(false) {}
267
268 template <class... _Args>
269 _LIBCPP_INLINE_VISIBILITY
270 constexpr explicit __optional_destruct_base(in_place_t, _Args&&... __args)
271 : __val_(_VSTD::forward<_Args>(__args)...),
272 __engaged_(true) {}
273
274 _LIBCPP_INLINE_VISIBILITY
275 void reset() noexcept
276 {
277 if (__engaged_)
278 {
279 __engaged_ = false;
280 }
281 }
282};
283
284template <class _Tp, bool = is_reference<_Tp>::value>
285struct __optional_storage_base : __optional_destruct_base<_Tp>
286{
287 using __base = __optional_destruct_base<_Tp>;
288 using value_type = _Tp;
289 using __base::__base;
290
291 _LIBCPP_INLINE_VISIBILITY
292 constexpr bool has_value() const noexcept
293 {
294 return this->__engaged_;
295 }
296
297 _LIBCPP_INLINE_VISIBILITY
298 constexpr value_type& __get() & noexcept
299 {
300 return this->__val_;
301 }
302 _LIBCPP_INLINE_VISIBILITY
303 constexpr const value_type& __get() const& noexcept
304 {
305 return this->__val_;
306 }
307 _LIBCPP_INLINE_VISIBILITY
308 constexpr value_type&& __get() && noexcept
309 {
310 return _VSTD::move(this->__val_);
311 }
312 _LIBCPP_INLINE_VISIBILITY
313 constexpr const value_type&& __get() const&& noexcept
314 {
315 return _VSTD::move(this->__val_);
316 }
317
318 template <class... _Args>
319 _LIBCPP_INLINE_VISIBILITY
320 void __construct(_Args&&... __args)
321 {
322 _LIBCPP_ASSERT(!has_value(), "__construct called for engaged __optional_storage");
323 ::new((void*)_VSTD::addressof(this->__val_)) value_type(_VSTD::forward<_Args>(__args)...);
324 this->__engaged_ = true;
325 }
326
327 template <class _That>
328 _LIBCPP_INLINE_VISIBILITY
329 void __construct_from(_That&& __opt)
330 {
331 if (__opt.has_value())
332 __construct(_VSTD::forward<_That>(__opt).__get());
333 }
334
335 template <class _That>
336 _LIBCPP_INLINE_VISIBILITY
337 void __assign_from(_That&& __opt)
338 {
339 if (this->__engaged_ == __opt.has_value())
340 {
341 if (this->__engaged_)
342 this->__val_ = _VSTD::forward<_That>(__opt).__get();
343 }
344 else
345 {
346 if (this->__engaged_)
347 this->reset();
348 else
349 __construct(_VSTD::forward<_That>(__opt).__get());
350 }
351 }
352};
353
354// optional<T&> is currently required ill-formed, however it may to be in the
355// future. For this reason it has already been implemented to ensure we can
356// make the change in an ABI compatible manner.
357template <class _Tp>
358struct __optional_storage_base<_Tp, true>
359{
360 using value_type = _Tp;
361 using __raw_type = remove_reference_t<_Tp>;
362 __raw_type* __value_;
363
364 template <class _Up>
365 static constexpr bool __can_bind_reference() {
366 using _RawUp = typename remove_reference<_Up>::type;
367 using _UpPtr = _RawUp*;
368 using _RawTp = typename remove_reference<_Tp>::type;
369 using _TpPtr = _RawTp*;
370 using _CheckLValueArg = integral_constant<bool,
371 (is_lvalue_reference<_Up>::value && is_convertible<_UpPtr, _TpPtr>::value)
372 || is_same<_RawUp, reference_wrapper<_RawTp>>::value
373 || is_same<_RawUp, reference_wrapper<typename remove_const<_RawTp>::type>>::value
374 >;
375 return (is_lvalue_reference<_Tp>::value && _CheckLValueArg::value)
376 || (is_rvalue_reference<_Tp>::value && !is_lvalue_reference<_Up>::value &&
377 is_convertible<_UpPtr, _TpPtr>::value);
378 }
379
380 _LIBCPP_INLINE_VISIBILITY
381 constexpr __optional_storage_base() noexcept
382 : __value_(nullptr) {}
383
384 template <class _UArg>
385 _LIBCPP_INLINE_VISIBILITY
386 constexpr explicit __optional_storage_base(in_place_t, _UArg&& __uarg)
387 : __value_(_VSTD::addressof(__uarg))
388 {
389 static_assert(__can_bind_reference<_UArg>(),
390 "Attempted to construct a reference element in tuple from a "
391 "possible temporary");
392 }
393
394 _LIBCPP_INLINE_VISIBILITY
395 void reset() noexcept { __value_ = nullptr; }
396
397 _LIBCPP_INLINE_VISIBILITY
398 constexpr bool has_value() const noexcept
399 { return __value_ != nullptr; }
400
401 _LIBCPP_INLINE_VISIBILITY
402 constexpr value_type& __get() const& noexcept
403 { return *__value_; }
404
405 _LIBCPP_INLINE_VISIBILITY
406 constexpr value_type&& __get() const&& noexcept
407 { return _VSTD::forward<value_type>(*__value_); }
408
409 template <class _UArg>
410 _LIBCPP_INLINE_VISIBILITY
411 void __construct(_UArg&& __val)
412 {
413 _LIBCPP_ASSERT(!has_value(), "__construct called for engaged __optional_storage");
414 static_assert(__can_bind_reference<_UArg>(),
415 "Attempted to construct a reference element in tuple from a "
416 "possible temporary");
417 __value_ = _VSTD::addressof(__val);
418 }
419
420 template <class _That>
421 _LIBCPP_INLINE_VISIBILITY
422 void __construct_from(_That&& __opt)
423 {
424 if (__opt.has_value())
425 __construct(_VSTD::forward<_That>(__opt).__get());
426 }
427
428 template <class _That>
429 _LIBCPP_INLINE_VISIBILITY
430 void __assign_from(_That&& __opt)
431 {
432 if (has_value() == __opt.has_value())
433 {
434 if (has_value())
435 *__value_ = _VSTD::forward<_That>(__opt).__get();
436 }
437 else
438 {
439 if (has_value())
440 reset();
441 else
442 __construct(_VSTD::forward<_That>(__opt).__get());
443 }
444 }
445};
446
Casey Carterc189f7f2017-07-09 17:15:49 +0000447template <class _Tp, bool = is_trivially_copy_constructible<_Tp>::value>
448struct __optional_copy_base : __optional_storage_base<_Tp>
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000449{
450 using __optional_storage_base<_Tp>::__optional_storage_base;
451};
452
453template <class _Tp>
Casey Carterc189f7f2017-07-09 17:15:49 +0000454struct __optional_copy_base<_Tp, false> : __optional_storage_base<_Tp>
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000455{
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000456 using __optional_storage_base<_Tp>::__optional_storage_base;
457
458 _LIBCPP_INLINE_VISIBILITY
Casey Carterc189f7f2017-07-09 17:15:49 +0000459 __optional_copy_base() = default;
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000460
461 _LIBCPP_INLINE_VISIBILITY
Casey Carterc189f7f2017-07-09 17:15:49 +0000462 __optional_copy_base(const __optional_copy_base& __opt)
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000463 {
464 this->__construct_from(__opt);
465 }
466
467 _LIBCPP_INLINE_VISIBILITY
Casey Carterc189f7f2017-07-09 17:15:49 +0000468 __optional_copy_base(__optional_copy_base&&) = default;
469 _LIBCPP_INLINE_VISIBILITY
470 __optional_copy_base& operator=(const __optional_copy_base&) = default;
471 _LIBCPP_INLINE_VISIBILITY
472 __optional_copy_base& operator=(__optional_copy_base&&) = default;
473};
474
475template <class _Tp, bool = is_trivially_move_constructible<_Tp>::value>
476struct __optional_move_base : __optional_copy_base<_Tp>
477{
478 using __optional_copy_base<_Tp>::__optional_copy_base;
479};
480
481template <class _Tp>
482struct __optional_move_base<_Tp, false> : __optional_copy_base<_Tp>
483{
484 using value_type = _Tp;
485 using __optional_copy_base<_Tp>::__optional_copy_base;
486
487 _LIBCPP_INLINE_VISIBILITY
488 __optional_move_base() = default;
489 _LIBCPP_INLINE_VISIBILITY
490 __optional_move_base(const __optional_move_base&) = default;
491
492 _LIBCPP_INLINE_VISIBILITY
493 __optional_move_base(__optional_move_base&& __opt)
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000494 noexcept(is_nothrow_move_constructible_v<value_type>)
495 {
496 this->__construct_from(_VSTD::move(__opt));
497 }
498
499 _LIBCPP_INLINE_VISIBILITY
Casey Carterc189f7f2017-07-09 17:15:49 +0000500 __optional_move_base& operator=(const __optional_move_base&) = default;
501 _LIBCPP_INLINE_VISIBILITY
502 __optional_move_base& operator=(__optional_move_base&&) = default;
503};
504
505template <class _Tp, bool =
506 is_trivially_destructible<_Tp>::value &&
507 is_trivially_copy_constructible<_Tp>::value &&
508 is_trivially_copy_assignable<_Tp>::value>
509struct __optional_copy_assign_base : __optional_move_base<_Tp>
510{
511 using __optional_move_base<_Tp>::__optional_move_base;
512};
513
514template <class _Tp>
515struct __optional_copy_assign_base<_Tp, false> : __optional_move_base<_Tp>
516{
517 using __optional_move_base<_Tp>::__optional_move_base;
518
519 _LIBCPP_INLINE_VISIBILITY
520 __optional_copy_assign_base() = default;
521 _LIBCPP_INLINE_VISIBILITY
522 __optional_copy_assign_base(const __optional_copy_assign_base&) = default;
523 _LIBCPP_INLINE_VISIBILITY
524 __optional_copy_assign_base(__optional_copy_assign_base&&) = default;
525
526 _LIBCPP_INLINE_VISIBILITY
527 __optional_copy_assign_base& operator=(const __optional_copy_assign_base& __opt)
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000528 {
529 this->__assign_from(__opt);
530 return *this;
531 }
532
533 _LIBCPP_INLINE_VISIBILITY
Casey Carterc189f7f2017-07-09 17:15:49 +0000534 __optional_copy_assign_base& operator=(__optional_copy_assign_base&&) = default;
535};
536
537template <class _Tp, bool =
538 is_trivially_destructible<_Tp>::value &&
539 is_trivially_move_constructible<_Tp>::value &&
540 is_trivially_move_assignable<_Tp>::value>
541struct __optional_move_assign_base : __optional_copy_assign_base<_Tp>
542{
543 using __optional_copy_assign_base<_Tp>::__optional_copy_assign_base;
544};
545
546template <class _Tp>
547struct __optional_move_assign_base<_Tp, false> : __optional_copy_assign_base<_Tp>
548{
549 using value_type = _Tp;
550 using __optional_copy_assign_base<_Tp>::__optional_copy_assign_base;
551
552 _LIBCPP_INLINE_VISIBILITY
553 __optional_move_assign_base() = default;
554 _LIBCPP_INLINE_VISIBILITY
555 __optional_move_assign_base(const __optional_move_assign_base& __opt) = default;
556 _LIBCPP_INLINE_VISIBILITY
557 __optional_move_assign_base(__optional_move_assign_base&&) = default;
558 _LIBCPP_INLINE_VISIBILITY
559 __optional_move_assign_base& operator=(const __optional_move_assign_base&) = default;
560
561 _LIBCPP_INLINE_VISIBILITY
562 __optional_move_assign_base& operator=(__optional_move_assign_base&& __opt)
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000563 noexcept(is_nothrow_move_assignable_v<value_type> &&
564 is_nothrow_move_constructible_v<value_type>)
565 {
566 this->__assign_from(_VSTD::move(__opt));
567 return *this;
568 }
569};
570
571template <class _Tp>
572using __optional_sfinae_ctor_base_t = __sfinae_ctor_base<
573 is_copy_constructible<_Tp>::value,
574 is_move_constructible<_Tp>::value
575>;
576
577template <class _Tp>
578using __optional_sfinae_assign_base_t = __sfinae_assign_base<
579 (is_copy_constructible<_Tp>::value && is_copy_assignable<_Tp>::value),
580 (is_move_constructible<_Tp>::value && is_move_assignable<_Tp>::value)
581>;
582
583template <class _Tp>
584class optional
Casey Carterc189f7f2017-07-09 17:15:49 +0000585 : private __optional_move_assign_base<_Tp>
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000586 , private __optional_sfinae_ctor_base_t<_Tp>
587 , private __optional_sfinae_assign_base_t<_Tp>
588{
Casey Carterc189f7f2017-07-09 17:15:49 +0000589 using __base = __optional_move_assign_base<_Tp>;
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000590public:
591 using value_type = _Tp;
592
593private:
594 // Disable the reference extension using this static assert.
595 static_assert(!is_same_v<value_type, in_place_t>,
596 "instantiation of optional with in_place_t is ill-formed");
597 static_assert(!is_same_v<__uncvref_t<value_type>, nullopt_t>,
598 "instantiation of optional with nullopt_t is ill-formed");
599 static_assert(!is_reference_v<value_type>,
600 "instantiation of optional with a reference type is ill-formed");
601 static_assert(is_destructible_v<value_type>,
602 "instantiation of optional with a non-destructible type is ill-formed");
603
604 // LWG2756: conditionally explicit conversion from _Up
605 struct _CheckOptionalArgsConstructor {
606 template <class _Up>
607 static constexpr bool __enable_implicit() {
608 return is_constructible_v<_Tp, _Up&&> &&
609 is_convertible_v<_Up&&, _Tp>;
610 }
611
612 template <class _Up>
613 static constexpr bool __enable_explicit() {
614 return is_constructible_v<_Tp, _Up&&> &&
615 !is_convertible_v<_Up&&, _Tp>;
616 }
617 };
618 template <class _Up>
619 using _CheckOptionalArgsCtor = conditional_t<
Marshall Clowd5bbc242018-02-06 20:56:55 +0000620 !is_same_v<__uncvref_t<_Up>, in_place_t> &&
621 !is_same_v<__uncvref_t<_Up>, optional>,
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000622 _CheckOptionalArgsConstructor,
623 __check_tuple_constructor_fail
624 >;
625 template <class _QualUp>
626 struct _CheckOptionalLikeConstructor {
627 template <class _Up, class _Opt = optional<_Up>>
628 using __check_constructible_from_opt = __lazy_or<
629 is_constructible<_Tp, _Opt&>,
630 is_constructible<_Tp, _Opt const&>,
631 is_constructible<_Tp, _Opt&&>,
632 is_constructible<_Tp, _Opt const&&>,
633 is_convertible<_Opt&, _Tp>,
634 is_convertible<_Opt const&, _Tp>,
635 is_convertible<_Opt&&, _Tp>,
636 is_convertible<_Opt const&&, _Tp>
637 >;
638 template <class _Up, class _Opt = optional<_Up>>
639 using __check_assignable_from_opt = __lazy_or<
640 is_assignable<_Tp&, _Opt&>,
641 is_assignable<_Tp&, _Opt const&>,
642 is_assignable<_Tp&, _Opt&&>,
643 is_assignable<_Tp&, _Opt const&&>
644 >;
645 template <class _Up, class _QUp = _QualUp>
646 static constexpr bool __enable_implicit() {
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_explicit() {
652 return !is_convertible<_QUp, _Tp>::value &&
653 !__check_constructible_from_opt<_Up>::value;
654 }
655 template <class _Up, class _QUp = _QualUp>
656 static constexpr bool __enable_assign() {
657 // Construction and assignability of _Qup to _Tp has already been
658 // checked.
659 return !__check_constructible_from_opt<_Up>::value &&
660 !__check_assignable_from_opt<_Up>::value;
661 }
662 };
663
664 template <class _Up, class _QualUp>
665 using _CheckOptionalLikeCtor = conditional_t<
666 __lazy_and<
667 __lazy_not<is_same<_Up, _Tp>>,
668 is_constructible<_Tp, _QualUp>
669 >::value,
670 _CheckOptionalLikeConstructor<_QualUp>,
671 __check_tuple_constructor_fail
672 >;
673 template <class _Up, class _QualUp>
674 using _CheckOptionalLikeAssign = conditional_t<
675 __lazy_and<
676 __lazy_not<is_same<_Up, _Tp>>,
677 is_constructible<_Tp, _QualUp>,
678 is_assignable<_Tp&, _QualUp>
679 >::value,
680 _CheckOptionalLikeConstructor<_QualUp>,
681 __check_tuple_constructor_fail
682 >;
683public:
684
685 _LIBCPP_INLINE_VISIBILITY constexpr optional() noexcept {}
Marshall Clowd44e2e32017-05-17 15:30:01 +0000686 _LIBCPP_INLINE_VISIBILITY constexpr optional(const optional&) = default;
687 _LIBCPP_INLINE_VISIBILITY constexpr optional(optional&&) = default;
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000688 _LIBCPP_INLINE_VISIBILITY constexpr optional(nullopt_t) noexcept {}
689
690 template <class... _Args, class = enable_if_t<
691 is_constructible_v<value_type, _Args...>>
692 >
693 _LIBCPP_INLINE_VISIBILITY
694 constexpr explicit optional(in_place_t, _Args&&... __args)
695 : __base(in_place, _VSTD::forward<_Args>(__args)...) {}
696
697 template <class _Up, class... _Args, class = enable_if_t<
698 is_constructible_v<value_type, initializer_list<_Up>&, _Args...>>
699 >
700 _LIBCPP_INLINE_VISIBILITY
701 constexpr explicit optional(in_place_t, initializer_list<_Up> __il, _Args&&... __args)
702 : __base(in_place, __il, _VSTD::forward<_Args>(__args)...) {}
703
704 template <class _Up = value_type, enable_if_t<
705 _CheckOptionalArgsCtor<_Up>::template __enable_implicit<_Up>()
706 , int> = 0>
707 _LIBCPP_INLINE_VISIBILITY
708 constexpr optional(_Up&& __v)
709 : __base(in_place, _VSTD::forward<_Up>(__v)) {}
710
711 template <class _Up, enable_if_t<
712 _CheckOptionalArgsCtor<_Up>::template __enable_explicit<_Up>()
713 , int> = 0>
714 _LIBCPP_INLINE_VISIBILITY
715 constexpr explicit optional(_Up&& __v)
716 : __base(in_place, _VSTD::forward<_Up>(__v)) {}
717
718 // LWG2756: conditionally explicit conversion from const optional<_Up>&
719 template <class _Up, enable_if_t<
720 _CheckOptionalLikeCtor<_Up, _Up const&>::template __enable_implicit<_Up>()
721 , int> = 0>
722 _LIBCPP_INLINE_VISIBILITY
723 optional(const optional<_Up>& __v)
724 {
725 this->__construct_from(__v);
726 }
727 template <class _Up, enable_if_t<
728 _CheckOptionalLikeCtor<_Up, _Up const&>::template __enable_explicit<_Up>()
729 , int> = 0>
730 _LIBCPP_INLINE_VISIBILITY
731 explicit optional(const optional<_Up>& __v)
732 {
733 this->__construct_from(__v);
734 }
735
736 // LWG2756: conditionally explicit conversion from optional<_Up>&&
737 template <class _Up, enable_if_t<
738 _CheckOptionalLikeCtor<_Up, _Up &&>::template __enable_implicit<_Up>()
739 , int> = 0>
740 _LIBCPP_INLINE_VISIBILITY
741 optional(optional<_Up>&& __v)
742 {
743 this->__construct_from(_VSTD::move(__v));
744 }
745 template <class _Up, enable_if_t<
746 _CheckOptionalLikeCtor<_Up, _Up &&>::template __enable_explicit<_Up>()
747 , int> = 0>
748 _LIBCPP_INLINE_VISIBILITY
749 explicit optional(optional<_Up>&& __v)
750 {
751 this->__construct_from(_VSTD::move(__v));
752 }
753
754 _LIBCPP_INLINE_VISIBILITY
755 optional& operator=(nullopt_t) noexcept
756 {
757 reset();
758 return *this;
759 }
760
761 _LIBCPP_INLINE_VISIBILITY optional& operator=(const optional&) = default;
762 _LIBCPP_INLINE_VISIBILITY optional& operator=(optional&&) = default;
763
764 // LWG2756
765 template <class _Up = value_type,
766 class = enable_if_t
Eric Fiselierb9014262016-10-16 03:21:35 +0000767 <__lazy_and<
768 integral_constant<bool,
Marshall Clowd5bbc242018-02-06 20:56:55 +0000769 !is_same_v<__uncvref_t<_Up>, optional> &&
Eric Fiselierb9014262016-10-16 03:21:35 +0000770 !(is_same_v<_Up, value_type> && is_scalar_v<value_type>)
771 >,
772 is_constructible<value_type, _Up>,
773 is_assignable<value_type&, _Up>
774 >::value>
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000775 >
776 _LIBCPP_INLINE_VISIBILITY
777 optional&
778 operator=(_Up&& __v)
779 {
780 if (this->has_value())
781 this->__get() = _VSTD::forward<_Up>(__v);
782 else
783 this->__construct(_VSTD::forward<_Up>(__v));
784 return *this;
785 }
786
787 // LWG2756
788 template <class _Up, enable_if_t<
789 _CheckOptionalLikeAssign<_Up, _Up const&>::template __enable_assign<_Up>()
790 , int> = 0>
791 _LIBCPP_INLINE_VISIBILITY
792 optional&
793 operator=(const optional<_Up>& __v)
794 {
795 this->__assign_from(__v);
796 return *this;
797 }
798
799 // LWG2756
800 template <class _Up, enable_if_t<
801 _CheckOptionalLikeCtor<_Up, _Up &&>::template __enable_assign<_Up>()
802 , int> = 0>
803 _LIBCPP_INLINE_VISIBILITY
804 optional&
805 operator=(optional<_Up>&& __v)
806 {
807 this->__assign_from(_VSTD::move(__v));
808 return *this;
809 }
810
811 template <class... _Args,
812 class = enable_if_t
813 <
814 is_constructible_v<value_type, _Args...>
815 >
816 >
817 _LIBCPP_INLINE_VISIBILITY
Marshall Clow45ff9822017-04-12 22:51:27 +0000818 _Tp &
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000819 emplace(_Args&&... __args)
820 {
821 reset();
822 this->__construct(_VSTD::forward<_Args>(__args)...);
Marshall Clow45ff9822017-04-12 22:51:27 +0000823 return this->__get();
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000824 }
825
826 template <class _Up, class... _Args,
827 class = enable_if_t
828 <
829 is_constructible_v<value_type, initializer_list<_Up>&, _Args...>
830 >
831 >
832 _LIBCPP_INLINE_VISIBILITY
Marshall Clow45ff9822017-04-12 22:51:27 +0000833 _Tp &
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000834 emplace(initializer_list<_Up> __il, _Args&&... __args)
835 {
836 reset();
837 this->__construct(__il, _VSTD::forward<_Args>(__args)...);
Marshall Clow45ff9822017-04-12 22:51:27 +0000838 return this->__get();
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000839 }
840
841 _LIBCPP_INLINE_VISIBILITY
842 void swap(optional& __opt)
843 noexcept(is_nothrow_move_constructible_v<value_type> &&
844 is_nothrow_swappable_v<value_type>)
845 {
846 if (this->has_value() == __opt.has_value())
847 {
848 using _VSTD::swap;
849 if (this->has_value())
850 swap(this->__get(), __opt.__get());
851 }
852 else
853 {
854 if (this->has_value())
855 {
856 __opt.__construct(_VSTD::move(this->__get()));
857 reset();
858 }
859 else
860 {
861 this->__construct(_VSTD::move(__opt.__get()));
862 __opt.reset();
863 }
864 }
865 }
866
867 _LIBCPP_INLINE_VISIBILITY
868 constexpr
869 add_pointer_t<value_type const>
870 operator->() const
871 {
872 _LIBCPP_ASSERT(this->has_value(), "optional operator-> called for disengaged value");
873#ifndef _LIBCPP_HAS_NO_BUILTIN_ADDRESSOF
874 return _VSTD::addressof(this->__get());
875#else
876 return __operator_arrow(__has_operator_addressof<value_type>{}, this->__get());
877#endif
878 }
879
880 _LIBCPP_INLINE_VISIBILITY
881 constexpr
882 add_pointer_t<value_type>
883 operator->()
884 {
885 _LIBCPP_ASSERT(this->has_value(), "optional operator-> called for disengaged value");
886#ifndef _LIBCPP_HAS_NO_BUILTIN_ADDRESSOF
887 return _VSTD::addressof(this->__get());
888#else
889 return __operator_arrow(__has_operator_addressof<value_type>{}, this->__get());
890#endif
891 }
892
893 _LIBCPP_INLINE_VISIBILITY
894 constexpr
895 const value_type&
896 operator*() const&
897 {
898 _LIBCPP_ASSERT(this->has_value(), "optional operator* called for disengaged value");
899 return this->__get();
900 }
901
902 _LIBCPP_INLINE_VISIBILITY
903 constexpr
904 value_type&
905 operator*() &
906 {
907 _LIBCPP_ASSERT(this->has_value(), "optional operator* called for disengaged value");
908 return this->__get();
909 }
910
911 _LIBCPP_INLINE_VISIBILITY
912 constexpr
913 value_type&&
914 operator*() &&
915 {
916 _LIBCPP_ASSERT(this->has_value(), "optional operator* called for disengaged value");
917 return _VSTD::move(this->__get());
918 }
919
920 _LIBCPP_INLINE_VISIBILITY
921 constexpr
922 const value_type&&
923 operator*() const&&
924 {
925 _LIBCPP_ASSERT(this->has_value(), "optional operator* called for disengaged value");
926 return _VSTD::move(this->__get());
927 }
928
929 _LIBCPP_INLINE_VISIBILITY
930 constexpr explicit operator bool() const noexcept { return has_value(); }
931
932 using __base::has_value;
933 using __base::__get;
934
935 _LIBCPP_INLINE_VISIBILITY
936 constexpr value_type const& value() const&
937 {
938 if (!this->has_value())
939 __throw_bad_optional_access();
940 return this->__get();
941 }
942
943 _LIBCPP_INLINE_VISIBILITY
944 constexpr value_type& value() &
945 {
946 if (!this->has_value())
947 __throw_bad_optional_access();
948 return this->__get();
949 }
950
951 _LIBCPP_INLINE_VISIBILITY
952 constexpr value_type&& value() &&
953 {
954 if (!this->has_value())
955 __throw_bad_optional_access();
956 return _VSTD::move(this->__get());
957 }
958
959 _LIBCPP_INLINE_VISIBILITY
960 constexpr value_type const&& value() const&&
961 {
962 if (!this->has_value())
963 __throw_bad_optional_access();
964 return _VSTD::move(this->__get());
965 }
966
967 template <class _Up>
968 _LIBCPP_INLINE_VISIBILITY
969 constexpr value_type value_or(_Up&& __v) const&
970 {
971 static_assert(is_copy_constructible_v<value_type>,
972 "optional<T>::value_or: T must be copy constructible");
973 static_assert(is_convertible_v<_Up, value_type>,
974 "optional<T>::value_or: U must be convertible to T");
975 return this->has_value() ? this->__get() :
976 static_cast<value_type>(_VSTD::forward<_Up>(__v));
977 }
978
979 template <class _Up>
980 _LIBCPP_INLINE_VISIBILITY
Casey Cartercb05fae2017-06-06 18:47:26 +0000981 constexpr value_type value_or(_Up&& __v) &&
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000982 {
983 static_assert(is_move_constructible_v<value_type>,
984 "optional<T>::value_or: T must be move constructible");
985 static_assert(is_convertible_v<_Up, value_type>,
986 "optional<T>::value_or: U must be convertible to T");
987 return this->has_value() ? _VSTD::move(this->__get()) :
988 static_cast<value_type>(_VSTD::forward<_Up>(__v));
989 }
990
991 using __base::reset;
992
993private:
994 template <class _Up>
995 _LIBCPP_INLINE_VISIBILITY
996 static _Up*
997 __operator_arrow(true_type, _Up& __x)
998 {
999 return _VSTD::addressof(__x);
1000 }
1001
1002 template <class _Up>
1003 _LIBCPP_INLINE_VISIBILITY
1004 static constexpr _Up*
1005 __operator_arrow(false_type, _Up& __x)
1006 {
1007 return &__x;
1008 }
1009};
1010
Marshall Clowe3c71ae2018-05-25 02:08:49 +00001011#ifndef _LIBCPP_HAS_NO_DEDUCTION_GUIDES
1012template<class T>
1013 optional(T) -> optional<T>;
1014#endif
1015
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001016// Comparisons between optionals
Eric Fiselier8af90142017-03-30 20:06:52 +00001017template <class _Tp, class _Up>
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001018_LIBCPP_INLINE_VISIBILITY constexpr
1019enable_if_t<
1020 is_convertible_v<decltype(_VSTD::declval<const _Tp&>() ==
Eric Fiselier8af90142017-03-30 20:06:52 +00001021 _VSTD::declval<const _Up&>()), bool>,
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001022 bool
1023>
Eric Fiselier8af90142017-03-30 20:06:52 +00001024operator==(const optional<_Tp>& __x, const optional<_Up>& __y)
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001025{
1026 if (static_cast<bool>(__x) != static_cast<bool>(__y))
1027 return false;
1028 if (!static_cast<bool>(__x))
1029 return true;
1030 return *__x == *__y;
1031}
1032
Eric Fiselier8af90142017-03-30 20:06:52 +00001033template <class _Tp, class _Up>
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001034_LIBCPP_INLINE_VISIBILITY constexpr
1035enable_if_t<
1036 is_convertible_v<decltype(_VSTD::declval<const _Tp&>() !=
Eric Fiselier8af90142017-03-30 20:06:52 +00001037 _VSTD::declval<const _Up&>()), bool>,
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001038 bool
1039>
Eric Fiselier8af90142017-03-30 20:06:52 +00001040operator!=(const optional<_Tp>& __x, const optional<_Up>& __y)
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001041{
1042 if (static_cast<bool>(__x) != static_cast<bool>(__y))
1043 return true;
1044 if (!static_cast<bool>(__x))
1045 return false;
1046 return *__x != *__y;
1047}
1048
Eric Fiselier8af90142017-03-30 20:06:52 +00001049template <class _Tp, class _Up>
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001050_LIBCPP_INLINE_VISIBILITY constexpr
1051enable_if_t<
1052 is_convertible_v<decltype(_VSTD::declval<const _Tp&>() <
Eric Fiselier8af90142017-03-30 20:06:52 +00001053 _VSTD::declval<const _Up&>()), bool>,
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001054 bool
1055>
Eric Fiselier8af90142017-03-30 20:06:52 +00001056operator<(const optional<_Tp>& __x, const optional<_Up>& __y)
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001057{
1058 if (!static_cast<bool>(__y))
1059 return false;
1060 if (!static_cast<bool>(__x))
1061 return true;
1062 return *__x < *__y;
1063}
1064
Eric Fiselier8af90142017-03-30 20:06:52 +00001065template <class _Tp, class _Up>
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001066_LIBCPP_INLINE_VISIBILITY constexpr
1067enable_if_t<
1068 is_convertible_v<decltype(_VSTD::declval<const _Tp&>() >
Eric Fiselier8af90142017-03-30 20:06:52 +00001069 _VSTD::declval<const _Up&>()), bool>,
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001070 bool
1071>
Eric Fiselier8af90142017-03-30 20:06:52 +00001072operator>(const optional<_Tp>& __x, const optional<_Up>& __y)
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001073{
1074 if (!static_cast<bool>(__x))
1075 return false;
1076 if (!static_cast<bool>(__y))
1077 return true;
1078 return *__x > *__y;
1079}
1080
Eric Fiselier8af90142017-03-30 20:06:52 +00001081template <class _Tp, class _Up>
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001082_LIBCPP_INLINE_VISIBILITY constexpr
1083enable_if_t<
1084 is_convertible_v<decltype(_VSTD::declval<const _Tp&>() <=
Eric Fiselier8af90142017-03-30 20:06:52 +00001085 _VSTD::declval<const _Up&>()), bool>,
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001086 bool
1087>
Eric Fiselier8af90142017-03-30 20:06:52 +00001088operator<=(const optional<_Tp>& __x, const optional<_Up>& __y)
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001089{
1090 if (!static_cast<bool>(__x))
1091 return true;
1092 if (!static_cast<bool>(__y))
1093 return false;
1094 return *__x <= *__y;
1095}
1096
Eric Fiselier8af90142017-03-30 20:06:52 +00001097template <class _Tp, class _Up>
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001098_LIBCPP_INLINE_VISIBILITY constexpr
1099enable_if_t<
1100 is_convertible_v<decltype(_VSTD::declval<const _Tp&>() >=
Eric Fiselier8af90142017-03-30 20:06:52 +00001101 _VSTD::declval<const _Up&>()), bool>,
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001102 bool
1103>
Eric Fiselier8af90142017-03-30 20:06:52 +00001104operator>=(const optional<_Tp>& __x, const optional<_Up>& __y)
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001105{
1106 if (!static_cast<bool>(__y))
1107 return true;
1108 if (!static_cast<bool>(__x))
1109 return false;
1110 return *__x >= *__y;
1111}
1112
1113// Comparisons with nullopt
1114template <class _Tp>
1115_LIBCPP_INLINE_VISIBILITY constexpr
1116bool
1117operator==(const optional<_Tp>& __x, nullopt_t) noexcept
1118{
1119 return !static_cast<bool>(__x);
1120}
1121
1122template <class _Tp>
1123_LIBCPP_INLINE_VISIBILITY constexpr
1124bool
1125operator==(nullopt_t, const optional<_Tp>& __x) noexcept
1126{
1127 return !static_cast<bool>(__x);
1128}
1129
1130template <class _Tp>
1131_LIBCPP_INLINE_VISIBILITY constexpr
1132bool
1133operator!=(const optional<_Tp>& __x, nullopt_t) noexcept
1134{
1135 return static_cast<bool>(__x);
1136}
1137
1138template <class _Tp>
1139_LIBCPP_INLINE_VISIBILITY constexpr
1140bool
1141operator!=(nullopt_t, const optional<_Tp>& __x) noexcept
1142{
1143 return static_cast<bool>(__x);
1144}
1145
1146template <class _Tp>
1147_LIBCPP_INLINE_VISIBILITY constexpr
1148bool
1149operator<(const optional<_Tp>&, nullopt_t) noexcept
1150{
1151 return false;
1152}
1153
1154template <class _Tp>
1155_LIBCPP_INLINE_VISIBILITY constexpr
1156bool
1157operator<(nullopt_t, const optional<_Tp>& __x) noexcept
1158{
1159 return static_cast<bool>(__x);
1160}
1161
1162template <class _Tp>
1163_LIBCPP_INLINE_VISIBILITY constexpr
1164bool
1165operator<=(const optional<_Tp>& __x, nullopt_t) noexcept
1166{
1167 return !static_cast<bool>(__x);
1168}
1169
1170template <class _Tp>
1171_LIBCPP_INLINE_VISIBILITY constexpr
1172bool
Eric Fiselier6003c772016-12-23 23:37:52 +00001173operator<=(nullopt_t, const optional<_Tp>&) noexcept
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001174{
1175 return true;
1176}
1177
1178template <class _Tp>
1179_LIBCPP_INLINE_VISIBILITY constexpr
1180bool
1181operator>(const optional<_Tp>& __x, nullopt_t) noexcept
1182{
1183 return static_cast<bool>(__x);
1184}
1185
1186template <class _Tp>
1187_LIBCPP_INLINE_VISIBILITY constexpr
1188bool
Eric Fiselier6003c772016-12-23 23:37:52 +00001189operator>(nullopt_t, const optional<_Tp>&) noexcept
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001190{
1191 return false;
1192}
1193
1194template <class _Tp>
1195_LIBCPP_INLINE_VISIBILITY constexpr
1196bool
1197operator>=(const optional<_Tp>&, nullopt_t) noexcept
1198{
1199 return true;
1200}
1201
1202template <class _Tp>
1203_LIBCPP_INLINE_VISIBILITY constexpr
1204bool
1205operator>=(nullopt_t, const optional<_Tp>& __x) noexcept
1206{
1207 return !static_cast<bool>(__x);
1208}
1209
1210// Comparisons with T
Eric Fiselier8af90142017-03-30 20:06:52 +00001211template <class _Tp, class _Up>
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001212_LIBCPP_INLINE_VISIBILITY constexpr
1213enable_if_t<
1214 is_convertible_v<decltype(_VSTD::declval<const _Tp&>() ==
Eric Fiselier8af90142017-03-30 20:06:52 +00001215 _VSTD::declval<const _Up&>()), bool>,
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001216 bool
1217>
Eric Fiselier8af90142017-03-30 20:06:52 +00001218operator==(const optional<_Tp>& __x, const _Up& __v)
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001219{
1220 return static_cast<bool>(__x) ? *__x == __v : false;
1221}
1222
Eric Fiselier8af90142017-03-30 20:06:52 +00001223template <class _Tp, class _Up>
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001224_LIBCPP_INLINE_VISIBILITY constexpr
1225enable_if_t<
1226 is_convertible_v<decltype(_VSTD::declval<const _Tp&>() ==
Eric Fiselier8af90142017-03-30 20:06:52 +00001227 _VSTD::declval<const _Up&>()), bool>,
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001228 bool
1229>
Eric Fiselier8af90142017-03-30 20:06:52 +00001230operator==(const _Tp& __v, const optional<_Up>& __x)
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001231{
1232 return static_cast<bool>(__x) ? __v == *__x : false;
1233}
1234
Eric Fiselier8af90142017-03-30 20:06:52 +00001235template <class _Tp, class _Up>
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001236_LIBCPP_INLINE_VISIBILITY constexpr
1237enable_if_t<
1238 is_convertible_v<decltype(_VSTD::declval<const _Tp&>() !=
Eric Fiselier8af90142017-03-30 20:06:52 +00001239 _VSTD::declval<const _Up&>()), bool>,
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001240 bool
1241>
Eric Fiselier8af90142017-03-30 20:06:52 +00001242operator!=(const optional<_Tp>& __x, const _Up& __v)
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001243{
1244 return static_cast<bool>(__x) ? *__x != __v : true;
1245}
1246
Eric Fiselier8af90142017-03-30 20:06:52 +00001247template <class _Tp, class _Up>
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001248_LIBCPP_INLINE_VISIBILITY constexpr
1249enable_if_t<
1250 is_convertible_v<decltype(_VSTD::declval<const _Tp&>() !=
Eric Fiselier8af90142017-03-30 20:06:52 +00001251 _VSTD::declval<const _Up&>()), bool>,
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001252 bool
1253>
Eric Fiselier8af90142017-03-30 20:06:52 +00001254operator!=(const _Tp& __v, const optional<_Up>& __x)
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001255{
1256 return static_cast<bool>(__x) ? __v != *__x : true;
1257}
1258
Eric Fiselier8af90142017-03-30 20:06:52 +00001259template <class _Tp, class _Up>
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001260_LIBCPP_INLINE_VISIBILITY constexpr
1261enable_if_t<
1262 is_convertible_v<decltype(_VSTD::declval<const _Tp&>() <
Eric Fiselier8af90142017-03-30 20:06:52 +00001263 _VSTD::declval<const _Up&>()), bool>,
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001264 bool
1265>
Eric Fiselier8af90142017-03-30 20:06:52 +00001266operator<(const optional<_Tp>& __x, const _Up& __v)
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001267{
1268 return static_cast<bool>(__x) ? *__x < __v : true;
1269}
1270
Eric Fiselier8af90142017-03-30 20:06:52 +00001271template <class _Tp, class _Up>
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001272_LIBCPP_INLINE_VISIBILITY constexpr
1273enable_if_t<
1274 is_convertible_v<decltype(_VSTD::declval<const _Tp&>() <
Eric Fiselier8af90142017-03-30 20:06:52 +00001275 _VSTD::declval<const _Up&>()), bool>,
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001276 bool
1277>
Eric Fiselier8af90142017-03-30 20:06:52 +00001278operator<(const _Tp& __v, const optional<_Up>& __x)
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001279{
1280 return static_cast<bool>(__x) ? __v < *__x : false;
1281}
1282
Eric Fiselier8af90142017-03-30 20:06:52 +00001283template <class _Tp, class _Up>
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001284_LIBCPP_INLINE_VISIBILITY constexpr
1285enable_if_t<
1286 is_convertible_v<decltype(_VSTD::declval<const _Tp&>() <=
Eric Fiselier8af90142017-03-30 20:06:52 +00001287 _VSTD::declval<const _Up&>()), bool>,
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001288 bool
1289>
Eric Fiselier8af90142017-03-30 20:06:52 +00001290operator<=(const optional<_Tp>& __x, const _Up& __v)
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001291{
1292 return static_cast<bool>(__x) ? *__x <= __v : true;
1293}
1294
Eric Fiselier8af90142017-03-30 20:06:52 +00001295template <class _Tp, class _Up>
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001296_LIBCPP_INLINE_VISIBILITY constexpr
1297enable_if_t<
1298 is_convertible_v<decltype(_VSTD::declval<const _Tp&>() <=
Eric Fiselier8af90142017-03-30 20:06:52 +00001299 _VSTD::declval<const _Up&>()), bool>,
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001300 bool
1301>
Eric Fiselier8af90142017-03-30 20:06:52 +00001302operator<=(const _Tp& __v, const optional<_Up>& __x)
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001303{
1304 return static_cast<bool>(__x) ? __v <= *__x : false;
1305}
1306
Eric Fiselier8af90142017-03-30 20:06:52 +00001307template <class _Tp, class _Up>
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001308_LIBCPP_INLINE_VISIBILITY constexpr
1309enable_if_t<
1310 is_convertible_v<decltype(_VSTD::declval<const _Tp&>() >
Eric Fiselier8af90142017-03-30 20:06:52 +00001311 _VSTD::declval<const _Up&>()), bool>,
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001312 bool
1313>
Eric Fiselier8af90142017-03-30 20:06:52 +00001314operator>(const optional<_Tp>& __x, const _Up& __v)
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001315{
1316 return static_cast<bool>(__x) ? *__x > __v : false;
1317}
1318
Eric Fiselier8af90142017-03-30 20:06:52 +00001319template <class _Tp, class _Up>
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001320_LIBCPP_INLINE_VISIBILITY constexpr
1321enable_if_t<
1322 is_convertible_v<decltype(_VSTD::declval<const _Tp&>() >
Eric Fiselier8af90142017-03-30 20:06:52 +00001323 _VSTD::declval<const _Up&>()), bool>,
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001324 bool
1325>
Eric Fiselier8af90142017-03-30 20:06:52 +00001326operator>(const _Tp& __v, const optional<_Up>& __x)
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001327{
1328 return static_cast<bool>(__x) ? __v > *__x : true;
1329}
1330
Eric Fiselier8af90142017-03-30 20:06:52 +00001331template <class _Tp, class _Up>
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001332_LIBCPP_INLINE_VISIBILITY constexpr
1333enable_if_t<
1334 is_convertible_v<decltype(_VSTD::declval<const _Tp&>() >=
Eric Fiselier8af90142017-03-30 20:06:52 +00001335 _VSTD::declval<const _Up&>()), bool>,
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001336 bool
1337>
Eric Fiselier8af90142017-03-30 20:06:52 +00001338operator>=(const optional<_Tp>& __x, const _Up& __v)
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001339{
1340 return static_cast<bool>(__x) ? *__x >= __v : false;
1341}
1342
Eric Fiselier8af90142017-03-30 20:06:52 +00001343template <class _Tp, class _Up>
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001344_LIBCPP_INLINE_VISIBILITY constexpr
1345enable_if_t<
1346 is_convertible_v<decltype(_VSTD::declval<const _Tp&>() >=
Eric Fiselier8af90142017-03-30 20:06:52 +00001347 _VSTD::declval<const _Up&>()), bool>,
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001348 bool
1349>
Eric Fiselier8af90142017-03-30 20:06:52 +00001350operator>=(const _Tp& __v, const optional<_Up>& __x)
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001351{
1352 return static_cast<bool>(__x) ? __v >= *__x : true;
1353}
1354
1355
1356template <class _Tp>
1357inline _LIBCPP_INLINE_VISIBILITY
1358enable_if_t<
1359 is_move_constructible_v<_Tp> && is_swappable_v<_Tp>,
1360 void
1361>
1362swap(optional<_Tp>& __x, optional<_Tp>& __y) noexcept(noexcept(__x.swap(__y)))
1363{
1364 __x.swap(__y);
1365}
1366
1367template <class _Tp>
1368_LIBCPP_INLINE_VISIBILITY constexpr
1369optional<decay_t<_Tp>> make_optional(_Tp&& __v)
1370{
1371 return optional<decay_t<_Tp>>(_VSTD::forward<_Tp>(__v));
1372}
1373
1374template <class _Tp, class... _Args>
1375_LIBCPP_INLINE_VISIBILITY constexpr
1376optional<_Tp> make_optional(_Args&&... __args)
1377{
1378 return optional<_Tp>(in_place, _VSTD::forward<_Args>(__args)...);
1379}
1380
1381template <class _Tp, class _Up, class... _Args>
1382_LIBCPP_INLINE_VISIBILITY constexpr
1383optional<_Tp> make_optional(initializer_list<_Up> __il, _Args&&... __args)
1384{
1385 return optional<_Tp>(in_place, __il, _VSTD::forward<_Args>(__args)...);
1386}
1387
1388template <class _Tp>
Eric Fiselier698a97b2017-01-21 00:02:12 +00001389struct _LIBCPP_TEMPLATE_VIS hash<
1390 __enable_hash_helper<optional<_Tp>, remove_const_t<_Tp>>
1391>
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001392{
1393 typedef optional<_Tp> argument_type;
1394 typedef size_t result_type;
1395
1396 _LIBCPP_INLINE_VISIBILITY
Marshall Clow49036892017-03-23 02:40:28 +00001397 result_type operator()(const argument_type& __opt) const
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001398 {
Eric Fiselier698a97b2017-01-21 00:02:12 +00001399 return static_cast<bool>(__opt) ? hash<remove_const_t<_Tp>>()(*__opt) : 0;
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001400 }
1401};
1402
1403_LIBCPP_END_NAMESPACE_STD
1404
1405#endif // _LIBCPP_STD_VER > 14
1406
Eric Fiselierf4433a32017-05-31 22:07:49 +00001407_LIBCPP_POP_MACROS
1408
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001409#endif // _LIBCPP_OPTIONAL