blob: 544140f2366d50b3d0dd00219e28ad3c09bceef8 [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
Louis Dionnecef92e62018-11-19 15:37:04 +0000172class _LIBCPP_EXCEPTION_ABI _LIBCPP_AVAILABILITY_BAD_OPTIONAL_ACCESS 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
Louis Dionnecef92e62018-11-19 15:37:04 +0000189_LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000190void __throw_bad_optional_access() {
191#ifndef _LIBCPP_NO_EXCEPTIONS
192 throw bad_optional_access();
193#else
194 _VSTD::abort();
195#endif
196}
197
198struct nullopt_t
199{
200 struct __secret_tag { _LIBCPP_INLINE_VISIBILITY explicit __secret_tag() = default; };
201 _LIBCPP_INLINE_VISIBILITY constexpr explicit nullopt_t(__secret_tag, __secret_tag) noexcept {}
202};
203
Marshall Clowf1bf62f2018-01-02 17:17:01 +0000204_LIBCPP_INLINE_VAR constexpr nullopt_t nullopt{nullopt_t::__secret_tag{}, nullopt_t::__secret_tag{}};
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000205
206template <class _Tp, bool = is_trivially_destructible<_Tp>::value>
207struct __optional_destruct_base;
208
209template <class _Tp>
210struct __optional_destruct_base<_Tp, false>
211{
212 typedef _Tp value_type;
213 static_assert(is_object_v<value_type>,
214 "instantiation of optional with a non-object type is undefined behavior");
215 union
216 {
217 char __null_state_;
218 value_type __val_;
219 };
220 bool __engaged_;
221
222 _LIBCPP_INLINE_VISIBILITY
223 ~__optional_destruct_base()
224 {
225 if (__engaged_)
226 __val_.~value_type();
227 }
228
229 _LIBCPP_INLINE_VISIBILITY
230 constexpr __optional_destruct_base() noexcept
231 : __null_state_(),
232 __engaged_(false) {}
233
234 template <class... _Args>
235 _LIBCPP_INLINE_VISIBILITY
236 constexpr explicit __optional_destruct_base(in_place_t, _Args&&... __args)
237 : __val_(_VSTD::forward<_Args>(__args)...),
238 __engaged_(true) {}
239
240 _LIBCPP_INLINE_VISIBILITY
241 void reset() noexcept
242 {
243 if (__engaged_)
244 {
245 __val_.~value_type();
246 __engaged_ = false;
247 }
248 }
249};
250
251template <class _Tp>
252struct __optional_destruct_base<_Tp, true>
253{
254 typedef _Tp value_type;
255 static_assert(is_object_v<value_type>,
256 "instantiation of optional with a non-object type is undefined behavior");
257 union
258 {
259 char __null_state_;
260 value_type __val_;
261 };
262 bool __engaged_;
263
264 _LIBCPP_INLINE_VISIBILITY
265 constexpr __optional_destruct_base() noexcept
266 : __null_state_(),
267 __engaged_(false) {}
268
269 template <class... _Args>
270 _LIBCPP_INLINE_VISIBILITY
271 constexpr explicit __optional_destruct_base(in_place_t, _Args&&... __args)
272 : __val_(_VSTD::forward<_Args>(__args)...),
273 __engaged_(true) {}
274
275 _LIBCPP_INLINE_VISIBILITY
276 void reset() noexcept
277 {
278 if (__engaged_)
279 {
280 __engaged_ = false;
281 }
282 }
283};
284
285template <class _Tp, bool = is_reference<_Tp>::value>
286struct __optional_storage_base : __optional_destruct_base<_Tp>
287{
288 using __base = __optional_destruct_base<_Tp>;
289 using value_type = _Tp;
290 using __base::__base;
291
292 _LIBCPP_INLINE_VISIBILITY
293 constexpr bool has_value() const noexcept
294 {
295 return this->__engaged_;
296 }
297
298 _LIBCPP_INLINE_VISIBILITY
299 constexpr value_type& __get() & noexcept
300 {
301 return this->__val_;
302 }
303 _LIBCPP_INLINE_VISIBILITY
304 constexpr const value_type& __get() const& noexcept
305 {
306 return this->__val_;
307 }
308 _LIBCPP_INLINE_VISIBILITY
309 constexpr value_type&& __get() && noexcept
310 {
311 return _VSTD::move(this->__val_);
312 }
313 _LIBCPP_INLINE_VISIBILITY
314 constexpr const value_type&& __get() const&& noexcept
315 {
316 return _VSTD::move(this->__val_);
317 }
318
319 template <class... _Args>
320 _LIBCPP_INLINE_VISIBILITY
321 void __construct(_Args&&... __args)
322 {
323 _LIBCPP_ASSERT(!has_value(), "__construct called for engaged __optional_storage");
324 ::new((void*)_VSTD::addressof(this->__val_)) value_type(_VSTD::forward<_Args>(__args)...);
325 this->__engaged_ = true;
326 }
327
328 template <class _That>
329 _LIBCPP_INLINE_VISIBILITY
330 void __construct_from(_That&& __opt)
331 {
332 if (__opt.has_value())
333 __construct(_VSTD::forward<_That>(__opt).__get());
334 }
335
336 template <class _That>
337 _LIBCPP_INLINE_VISIBILITY
338 void __assign_from(_That&& __opt)
339 {
340 if (this->__engaged_ == __opt.has_value())
341 {
342 if (this->__engaged_)
343 this->__val_ = _VSTD::forward<_That>(__opt).__get();
344 }
345 else
346 {
347 if (this->__engaged_)
348 this->reset();
349 else
350 __construct(_VSTD::forward<_That>(__opt).__get());
351 }
352 }
353};
354
355// optional<T&> is currently required ill-formed, however it may to be in the
356// future. For this reason it has already been implemented to ensure we can
357// make the change in an ABI compatible manner.
358template <class _Tp>
359struct __optional_storage_base<_Tp, true>
360{
361 using value_type = _Tp;
362 using __raw_type = remove_reference_t<_Tp>;
363 __raw_type* __value_;
364
365 template <class _Up>
366 static constexpr bool __can_bind_reference() {
367 using _RawUp = typename remove_reference<_Up>::type;
368 using _UpPtr = _RawUp*;
369 using _RawTp = typename remove_reference<_Tp>::type;
370 using _TpPtr = _RawTp*;
371 using _CheckLValueArg = integral_constant<bool,
372 (is_lvalue_reference<_Up>::value && is_convertible<_UpPtr, _TpPtr>::value)
373 || is_same<_RawUp, reference_wrapper<_RawTp>>::value
374 || is_same<_RawUp, reference_wrapper<typename remove_const<_RawTp>::type>>::value
375 >;
376 return (is_lvalue_reference<_Tp>::value && _CheckLValueArg::value)
377 || (is_rvalue_reference<_Tp>::value && !is_lvalue_reference<_Up>::value &&
378 is_convertible<_UpPtr, _TpPtr>::value);
379 }
380
381 _LIBCPP_INLINE_VISIBILITY
382 constexpr __optional_storage_base() noexcept
383 : __value_(nullptr) {}
384
385 template <class _UArg>
386 _LIBCPP_INLINE_VISIBILITY
387 constexpr explicit __optional_storage_base(in_place_t, _UArg&& __uarg)
388 : __value_(_VSTD::addressof(__uarg))
389 {
390 static_assert(__can_bind_reference<_UArg>(),
391 "Attempted to construct a reference element in tuple from a "
392 "possible temporary");
393 }
394
395 _LIBCPP_INLINE_VISIBILITY
396 void reset() noexcept { __value_ = nullptr; }
397
398 _LIBCPP_INLINE_VISIBILITY
399 constexpr bool has_value() const noexcept
400 { return __value_ != nullptr; }
401
402 _LIBCPP_INLINE_VISIBILITY
403 constexpr value_type& __get() const& noexcept
404 { return *__value_; }
405
406 _LIBCPP_INLINE_VISIBILITY
407 constexpr value_type&& __get() const&& noexcept
408 { return _VSTD::forward<value_type>(*__value_); }
409
410 template <class _UArg>
411 _LIBCPP_INLINE_VISIBILITY
412 void __construct(_UArg&& __val)
413 {
414 _LIBCPP_ASSERT(!has_value(), "__construct called for engaged __optional_storage");
415 static_assert(__can_bind_reference<_UArg>(),
416 "Attempted to construct a reference element in tuple from a "
417 "possible temporary");
418 __value_ = _VSTD::addressof(__val);
419 }
420
421 template <class _That>
422 _LIBCPP_INLINE_VISIBILITY
423 void __construct_from(_That&& __opt)
424 {
425 if (__opt.has_value())
426 __construct(_VSTD::forward<_That>(__opt).__get());
427 }
428
429 template <class _That>
430 _LIBCPP_INLINE_VISIBILITY
431 void __assign_from(_That&& __opt)
432 {
433 if (has_value() == __opt.has_value())
434 {
435 if (has_value())
436 *__value_ = _VSTD::forward<_That>(__opt).__get();
437 }
438 else
439 {
440 if (has_value())
441 reset();
442 else
443 __construct(_VSTD::forward<_That>(__opt).__get());
444 }
445 }
446};
447
Casey Carterc189f7f2017-07-09 17:15:49 +0000448template <class _Tp, bool = is_trivially_copy_constructible<_Tp>::value>
449struct __optional_copy_base : __optional_storage_base<_Tp>
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000450{
451 using __optional_storage_base<_Tp>::__optional_storage_base;
452};
453
454template <class _Tp>
Casey Carterc189f7f2017-07-09 17:15:49 +0000455struct __optional_copy_base<_Tp, false> : __optional_storage_base<_Tp>
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000456{
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000457 using __optional_storage_base<_Tp>::__optional_storage_base;
458
459 _LIBCPP_INLINE_VISIBILITY
Casey Carterc189f7f2017-07-09 17:15:49 +0000460 __optional_copy_base() = default;
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000461
462 _LIBCPP_INLINE_VISIBILITY
Casey Carterc189f7f2017-07-09 17:15:49 +0000463 __optional_copy_base(const __optional_copy_base& __opt)
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000464 {
465 this->__construct_from(__opt);
466 }
467
468 _LIBCPP_INLINE_VISIBILITY
Casey Carterc189f7f2017-07-09 17:15:49 +0000469 __optional_copy_base(__optional_copy_base&&) = default;
470 _LIBCPP_INLINE_VISIBILITY
471 __optional_copy_base& operator=(const __optional_copy_base&) = default;
472 _LIBCPP_INLINE_VISIBILITY
473 __optional_copy_base& operator=(__optional_copy_base&&) = default;
474};
475
476template <class _Tp, bool = is_trivially_move_constructible<_Tp>::value>
477struct __optional_move_base : __optional_copy_base<_Tp>
478{
479 using __optional_copy_base<_Tp>::__optional_copy_base;
480};
481
482template <class _Tp>
483struct __optional_move_base<_Tp, false> : __optional_copy_base<_Tp>
484{
485 using value_type = _Tp;
486 using __optional_copy_base<_Tp>::__optional_copy_base;
487
488 _LIBCPP_INLINE_VISIBILITY
489 __optional_move_base() = default;
490 _LIBCPP_INLINE_VISIBILITY
491 __optional_move_base(const __optional_move_base&) = default;
492
493 _LIBCPP_INLINE_VISIBILITY
494 __optional_move_base(__optional_move_base&& __opt)
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000495 noexcept(is_nothrow_move_constructible_v<value_type>)
496 {
497 this->__construct_from(_VSTD::move(__opt));
498 }
499
500 _LIBCPP_INLINE_VISIBILITY
Casey Carterc189f7f2017-07-09 17:15:49 +0000501 __optional_move_base& operator=(const __optional_move_base&) = default;
502 _LIBCPP_INLINE_VISIBILITY
503 __optional_move_base& operator=(__optional_move_base&&) = default;
504};
505
506template <class _Tp, bool =
507 is_trivially_destructible<_Tp>::value &&
508 is_trivially_copy_constructible<_Tp>::value &&
509 is_trivially_copy_assignable<_Tp>::value>
510struct __optional_copy_assign_base : __optional_move_base<_Tp>
511{
512 using __optional_move_base<_Tp>::__optional_move_base;
513};
514
515template <class _Tp>
516struct __optional_copy_assign_base<_Tp, false> : __optional_move_base<_Tp>
517{
518 using __optional_move_base<_Tp>::__optional_move_base;
519
520 _LIBCPP_INLINE_VISIBILITY
521 __optional_copy_assign_base() = default;
522 _LIBCPP_INLINE_VISIBILITY
523 __optional_copy_assign_base(const __optional_copy_assign_base&) = default;
524 _LIBCPP_INLINE_VISIBILITY
525 __optional_copy_assign_base(__optional_copy_assign_base&&) = default;
526
527 _LIBCPP_INLINE_VISIBILITY
528 __optional_copy_assign_base& operator=(const __optional_copy_assign_base& __opt)
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000529 {
530 this->__assign_from(__opt);
531 return *this;
532 }
533
534 _LIBCPP_INLINE_VISIBILITY
Casey Carterc189f7f2017-07-09 17:15:49 +0000535 __optional_copy_assign_base& operator=(__optional_copy_assign_base&&) = default;
536};
537
538template <class _Tp, bool =
539 is_trivially_destructible<_Tp>::value &&
540 is_trivially_move_constructible<_Tp>::value &&
541 is_trivially_move_assignable<_Tp>::value>
542struct __optional_move_assign_base : __optional_copy_assign_base<_Tp>
543{
544 using __optional_copy_assign_base<_Tp>::__optional_copy_assign_base;
545};
546
547template <class _Tp>
548struct __optional_move_assign_base<_Tp, false> : __optional_copy_assign_base<_Tp>
549{
550 using value_type = _Tp;
551 using __optional_copy_assign_base<_Tp>::__optional_copy_assign_base;
552
553 _LIBCPP_INLINE_VISIBILITY
554 __optional_move_assign_base() = default;
555 _LIBCPP_INLINE_VISIBILITY
556 __optional_move_assign_base(const __optional_move_assign_base& __opt) = default;
557 _LIBCPP_INLINE_VISIBILITY
558 __optional_move_assign_base(__optional_move_assign_base&&) = default;
559 _LIBCPP_INLINE_VISIBILITY
560 __optional_move_assign_base& operator=(const __optional_move_assign_base&) = default;
561
562 _LIBCPP_INLINE_VISIBILITY
563 __optional_move_assign_base& operator=(__optional_move_assign_base&& __opt)
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000564 noexcept(is_nothrow_move_assignable_v<value_type> &&
565 is_nothrow_move_constructible_v<value_type>)
566 {
567 this->__assign_from(_VSTD::move(__opt));
568 return *this;
569 }
570};
571
572template <class _Tp>
573using __optional_sfinae_ctor_base_t = __sfinae_ctor_base<
574 is_copy_constructible<_Tp>::value,
575 is_move_constructible<_Tp>::value
576>;
577
578template <class _Tp>
579using __optional_sfinae_assign_base_t = __sfinae_assign_base<
580 (is_copy_constructible<_Tp>::value && is_copy_assignable<_Tp>::value),
581 (is_move_constructible<_Tp>::value && is_move_assignable<_Tp>::value)
582>;
583
584template <class _Tp>
585class optional
Casey Carterc189f7f2017-07-09 17:15:49 +0000586 : private __optional_move_assign_base<_Tp>
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000587 , private __optional_sfinae_ctor_base_t<_Tp>
588 , private __optional_sfinae_assign_base_t<_Tp>
589{
Casey Carterc189f7f2017-07-09 17:15:49 +0000590 using __base = __optional_move_assign_base<_Tp>;
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000591public:
592 using value_type = _Tp;
593
594private:
595 // Disable the reference extension using this static assert.
596 static_assert(!is_same_v<value_type, in_place_t>,
597 "instantiation of optional with in_place_t is ill-formed");
598 static_assert(!is_same_v<__uncvref_t<value_type>, nullopt_t>,
599 "instantiation of optional with nullopt_t is ill-formed");
600 static_assert(!is_reference_v<value_type>,
601 "instantiation of optional with a reference type is ill-formed");
602 static_assert(is_destructible_v<value_type>,
603 "instantiation of optional with a non-destructible type is ill-formed");
604
605 // LWG2756: conditionally explicit conversion from _Up
606 struct _CheckOptionalArgsConstructor {
607 template <class _Up>
608 static constexpr bool __enable_implicit() {
609 return is_constructible_v<_Tp, _Up&&> &&
610 is_convertible_v<_Up&&, _Tp>;
611 }
612
613 template <class _Up>
614 static constexpr bool __enable_explicit() {
615 return is_constructible_v<_Tp, _Up&&> &&
616 !is_convertible_v<_Up&&, _Tp>;
617 }
618 };
619 template <class _Up>
620 using _CheckOptionalArgsCtor = conditional_t<
Marshall Clowd5bbc242018-02-06 20:56:55 +0000621 !is_same_v<__uncvref_t<_Up>, in_place_t> &&
622 !is_same_v<__uncvref_t<_Up>, optional>,
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000623 _CheckOptionalArgsConstructor,
624 __check_tuple_constructor_fail
625 >;
626 template <class _QualUp>
627 struct _CheckOptionalLikeConstructor {
628 template <class _Up, class _Opt = optional<_Up>>
629 using __check_constructible_from_opt = __lazy_or<
630 is_constructible<_Tp, _Opt&>,
631 is_constructible<_Tp, _Opt const&>,
632 is_constructible<_Tp, _Opt&&>,
633 is_constructible<_Tp, _Opt const&&>,
634 is_convertible<_Opt&, _Tp>,
635 is_convertible<_Opt const&, _Tp>,
636 is_convertible<_Opt&&, _Tp>,
637 is_convertible<_Opt const&&, _Tp>
638 >;
639 template <class _Up, class _Opt = optional<_Up>>
640 using __check_assignable_from_opt = __lazy_or<
641 is_assignable<_Tp&, _Opt&>,
642 is_assignable<_Tp&, _Opt const&>,
643 is_assignable<_Tp&, _Opt&&>,
644 is_assignable<_Tp&, _Opt const&&>
645 >;
646 template <class _Up, class _QUp = _QualUp>
647 static constexpr bool __enable_implicit() {
648 return is_convertible<_QUp, _Tp>::value &&
649 !__check_constructible_from_opt<_Up>::value;
650 }
651 template <class _Up, class _QUp = _QualUp>
652 static constexpr bool __enable_explicit() {
653 return !is_convertible<_QUp, _Tp>::value &&
654 !__check_constructible_from_opt<_Up>::value;
655 }
656 template <class _Up, class _QUp = _QualUp>
657 static constexpr bool __enable_assign() {
658 // Construction and assignability of _Qup to _Tp has already been
659 // checked.
660 return !__check_constructible_from_opt<_Up>::value &&
661 !__check_assignable_from_opt<_Up>::value;
662 }
663 };
664
665 template <class _Up, class _QualUp>
666 using _CheckOptionalLikeCtor = conditional_t<
667 __lazy_and<
668 __lazy_not<is_same<_Up, _Tp>>,
669 is_constructible<_Tp, _QualUp>
670 >::value,
671 _CheckOptionalLikeConstructor<_QualUp>,
672 __check_tuple_constructor_fail
673 >;
674 template <class _Up, class _QualUp>
675 using _CheckOptionalLikeAssign = conditional_t<
676 __lazy_and<
677 __lazy_not<is_same<_Up, _Tp>>,
678 is_constructible<_Tp, _QualUp>,
679 is_assignable<_Tp&, _QualUp>
680 >::value,
681 _CheckOptionalLikeConstructor<_QualUp>,
682 __check_tuple_constructor_fail
683 >;
684public:
685
686 _LIBCPP_INLINE_VISIBILITY constexpr optional() noexcept {}
Marshall Clowd44e2e32017-05-17 15:30:01 +0000687 _LIBCPP_INLINE_VISIBILITY constexpr optional(const optional&) = default;
688 _LIBCPP_INLINE_VISIBILITY constexpr optional(optional&&) = default;
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000689 _LIBCPP_INLINE_VISIBILITY constexpr optional(nullopt_t) noexcept {}
690
691 template <class... _Args, class = enable_if_t<
692 is_constructible_v<value_type, _Args...>>
693 >
694 _LIBCPP_INLINE_VISIBILITY
695 constexpr explicit optional(in_place_t, _Args&&... __args)
696 : __base(in_place, _VSTD::forward<_Args>(__args)...) {}
697
698 template <class _Up, class... _Args, class = enable_if_t<
699 is_constructible_v<value_type, initializer_list<_Up>&, _Args...>>
700 >
701 _LIBCPP_INLINE_VISIBILITY
702 constexpr explicit optional(in_place_t, initializer_list<_Up> __il, _Args&&... __args)
703 : __base(in_place, __il, _VSTD::forward<_Args>(__args)...) {}
704
705 template <class _Up = value_type, enable_if_t<
706 _CheckOptionalArgsCtor<_Up>::template __enable_implicit<_Up>()
707 , int> = 0>
708 _LIBCPP_INLINE_VISIBILITY
709 constexpr optional(_Up&& __v)
710 : __base(in_place, _VSTD::forward<_Up>(__v)) {}
711
712 template <class _Up, enable_if_t<
713 _CheckOptionalArgsCtor<_Up>::template __enable_explicit<_Up>()
714 , int> = 0>
715 _LIBCPP_INLINE_VISIBILITY
716 constexpr explicit optional(_Up&& __v)
717 : __base(in_place, _VSTD::forward<_Up>(__v)) {}
718
719 // LWG2756: conditionally explicit conversion from const optional<_Up>&
720 template <class _Up, enable_if_t<
721 _CheckOptionalLikeCtor<_Up, _Up const&>::template __enable_implicit<_Up>()
722 , int> = 0>
723 _LIBCPP_INLINE_VISIBILITY
724 optional(const optional<_Up>& __v)
725 {
726 this->__construct_from(__v);
727 }
728 template <class _Up, enable_if_t<
729 _CheckOptionalLikeCtor<_Up, _Up const&>::template __enable_explicit<_Up>()
730 , int> = 0>
731 _LIBCPP_INLINE_VISIBILITY
732 explicit optional(const optional<_Up>& __v)
733 {
734 this->__construct_from(__v);
735 }
736
737 // LWG2756: conditionally explicit conversion from optional<_Up>&&
738 template <class _Up, enable_if_t<
739 _CheckOptionalLikeCtor<_Up, _Up &&>::template __enable_implicit<_Up>()
740 , int> = 0>
741 _LIBCPP_INLINE_VISIBILITY
742 optional(optional<_Up>&& __v)
743 {
744 this->__construct_from(_VSTD::move(__v));
745 }
746 template <class _Up, enable_if_t<
747 _CheckOptionalLikeCtor<_Up, _Up &&>::template __enable_explicit<_Up>()
748 , int> = 0>
749 _LIBCPP_INLINE_VISIBILITY
750 explicit optional(optional<_Up>&& __v)
751 {
752 this->__construct_from(_VSTD::move(__v));
753 }
754
755 _LIBCPP_INLINE_VISIBILITY
756 optional& operator=(nullopt_t) noexcept
757 {
758 reset();
759 return *this;
760 }
761
762 _LIBCPP_INLINE_VISIBILITY optional& operator=(const optional&) = default;
763 _LIBCPP_INLINE_VISIBILITY optional& operator=(optional&&) = default;
764
765 // LWG2756
766 template <class _Up = value_type,
767 class = enable_if_t
Eric Fiselierb9014262016-10-16 03:21:35 +0000768 <__lazy_and<
769 integral_constant<bool,
Marshall Clowd5bbc242018-02-06 20:56:55 +0000770 !is_same_v<__uncvref_t<_Up>, optional> &&
Eric Fiselierb9014262016-10-16 03:21:35 +0000771 !(is_same_v<_Up, value_type> && is_scalar_v<value_type>)
772 >,
773 is_constructible<value_type, _Up>,
774 is_assignable<value_type&, _Up>
775 >::value>
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000776 >
777 _LIBCPP_INLINE_VISIBILITY
778 optional&
779 operator=(_Up&& __v)
780 {
781 if (this->has_value())
782 this->__get() = _VSTD::forward<_Up>(__v);
783 else
784 this->__construct(_VSTD::forward<_Up>(__v));
785 return *this;
786 }
787
788 // LWG2756
789 template <class _Up, enable_if_t<
790 _CheckOptionalLikeAssign<_Up, _Up const&>::template __enable_assign<_Up>()
791 , int> = 0>
792 _LIBCPP_INLINE_VISIBILITY
793 optional&
794 operator=(const optional<_Up>& __v)
795 {
796 this->__assign_from(__v);
797 return *this;
798 }
799
800 // LWG2756
801 template <class _Up, enable_if_t<
802 _CheckOptionalLikeCtor<_Up, _Up &&>::template __enable_assign<_Up>()
803 , int> = 0>
804 _LIBCPP_INLINE_VISIBILITY
805 optional&
806 operator=(optional<_Up>&& __v)
807 {
808 this->__assign_from(_VSTD::move(__v));
809 return *this;
810 }
811
812 template <class... _Args,
813 class = enable_if_t
814 <
815 is_constructible_v<value_type, _Args...>
816 >
817 >
818 _LIBCPP_INLINE_VISIBILITY
Marshall Clow45ff9822017-04-12 22:51:27 +0000819 _Tp &
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000820 emplace(_Args&&... __args)
821 {
822 reset();
823 this->__construct(_VSTD::forward<_Args>(__args)...);
Marshall Clow45ff9822017-04-12 22:51:27 +0000824 return this->__get();
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000825 }
826
827 template <class _Up, class... _Args,
828 class = enable_if_t
829 <
830 is_constructible_v<value_type, initializer_list<_Up>&, _Args...>
831 >
832 >
833 _LIBCPP_INLINE_VISIBILITY
Marshall Clow45ff9822017-04-12 22:51:27 +0000834 _Tp &
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000835 emplace(initializer_list<_Up> __il, _Args&&... __args)
836 {
837 reset();
838 this->__construct(__il, _VSTD::forward<_Args>(__args)...);
Marshall Clow45ff9822017-04-12 22:51:27 +0000839 return this->__get();
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000840 }
841
842 _LIBCPP_INLINE_VISIBILITY
843 void swap(optional& __opt)
844 noexcept(is_nothrow_move_constructible_v<value_type> &&
845 is_nothrow_swappable_v<value_type>)
846 {
847 if (this->has_value() == __opt.has_value())
848 {
849 using _VSTD::swap;
850 if (this->has_value())
851 swap(this->__get(), __opt.__get());
852 }
853 else
854 {
855 if (this->has_value())
856 {
857 __opt.__construct(_VSTD::move(this->__get()));
858 reset();
859 }
860 else
861 {
862 this->__construct(_VSTD::move(__opt.__get()));
863 __opt.reset();
864 }
865 }
866 }
867
868 _LIBCPP_INLINE_VISIBILITY
869 constexpr
870 add_pointer_t<value_type const>
871 operator->() const
872 {
873 _LIBCPP_ASSERT(this->has_value(), "optional operator-> called for disengaged value");
874#ifndef _LIBCPP_HAS_NO_BUILTIN_ADDRESSOF
875 return _VSTD::addressof(this->__get());
876#else
877 return __operator_arrow(__has_operator_addressof<value_type>{}, this->__get());
878#endif
879 }
880
881 _LIBCPP_INLINE_VISIBILITY
882 constexpr
883 add_pointer_t<value_type>
884 operator->()
885 {
886 _LIBCPP_ASSERT(this->has_value(), "optional operator-> called for disengaged value");
887#ifndef _LIBCPP_HAS_NO_BUILTIN_ADDRESSOF
888 return _VSTD::addressof(this->__get());
889#else
890 return __operator_arrow(__has_operator_addressof<value_type>{}, this->__get());
891#endif
892 }
893
894 _LIBCPP_INLINE_VISIBILITY
895 constexpr
896 const value_type&
897 operator*() const&
898 {
899 _LIBCPP_ASSERT(this->has_value(), "optional operator* called for disengaged value");
900 return this->__get();
901 }
902
903 _LIBCPP_INLINE_VISIBILITY
904 constexpr
905 value_type&
906 operator*() &
907 {
908 _LIBCPP_ASSERT(this->has_value(), "optional operator* called for disengaged value");
909 return this->__get();
910 }
911
912 _LIBCPP_INLINE_VISIBILITY
913 constexpr
914 value_type&&
915 operator*() &&
916 {
917 _LIBCPP_ASSERT(this->has_value(), "optional operator* called for disengaged value");
918 return _VSTD::move(this->__get());
919 }
920
921 _LIBCPP_INLINE_VISIBILITY
922 constexpr
923 const value_type&&
924 operator*() const&&
925 {
926 _LIBCPP_ASSERT(this->has_value(), "optional operator* called for disengaged value");
927 return _VSTD::move(this->__get());
928 }
929
930 _LIBCPP_INLINE_VISIBILITY
931 constexpr explicit operator bool() const noexcept { return has_value(); }
932
933 using __base::has_value;
934 using __base::__get;
935
936 _LIBCPP_INLINE_VISIBILITY
Louis Dionnecef92e62018-11-19 15:37:04 +0000937 _LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000938 constexpr value_type const& value() const&
939 {
940 if (!this->has_value())
941 __throw_bad_optional_access();
942 return this->__get();
943 }
944
945 _LIBCPP_INLINE_VISIBILITY
Louis Dionnecef92e62018-11-19 15:37:04 +0000946 _LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000947 constexpr value_type& value() &
948 {
949 if (!this->has_value())
950 __throw_bad_optional_access();
951 return this->__get();
952 }
953
954 _LIBCPP_INLINE_VISIBILITY
Louis Dionnecef92e62018-11-19 15:37:04 +0000955 _LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000956 constexpr value_type&& value() &&
957 {
958 if (!this->has_value())
959 __throw_bad_optional_access();
960 return _VSTD::move(this->__get());
961 }
962
963 _LIBCPP_INLINE_VISIBILITY
Louis Dionnecef92e62018-11-19 15:37:04 +0000964 _LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000965 constexpr value_type const&& value() const&&
966 {
967 if (!this->has_value())
968 __throw_bad_optional_access();
969 return _VSTD::move(this->__get());
970 }
971
972 template <class _Up>
973 _LIBCPP_INLINE_VISIBILITY
974 constexpr value_type value_or(_Up&& __v) const&
975 {
976 static_assert(is_copy_constructible_v<value_type>,
977 "optional<T>::value_or: T must be copy constructible");
978 static_assert(is_convertible_v<_Up, value_type>,
979 "optional<T>::value_or: U must be convertible to T");
980 return this->has_value() ? this->__get() :
981 static_cast<value_type>(_VSTD::forward<_Up>(__v));
982 }
983
984 template <class _Up>
985 _LIBCPP_INLINE_VISIBILITY
Casey Cartercb05fae2017-06-06 18:47:26 +0000986 constexpr value_type value_or(_Up&& __v) &&
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000987 {
988 static_assert(is_move_constructible_v<value_type>,
989 "optional<T>::value_or: T must be move constructible");
990 static_assert(is_convertible_v<_Up, value_type>,
991 "optional<T>::value_or: U must be convertible to T");
992 return this->has_value() ? _VSTD::move(this->__get()) :
993 static_cast<value_type>(_VSTD::forward<_Up>(__v));
994 }
995
996 using __base::reset;
997
998private:
999 template <class _Up>
1000 _LIBCPP_INLINE_VISIBILITY
1001 static _Up*
1002 __operator_arrow(true_type, _Up& __x)
1003 {
1004 return _VSTD::addressof(__x);
1005 }
1006
1007 template <class _Up>
1008 _LIBCPP_INLINE_VISIBILITY
1009 static constexpr _Up*
1010 __operator_arrow(false_type, _Up& __x)
1011 {
1012 return &__x;
1013 }
1014};
1015
Marshall Clowe3c71ae2018-05-25 02:08:49 +00001016#ifndef _LIBCPP_HAS_NO_DEDUCTION_GUIDES
1017template<class T>
1018 optional(T) -> optional<T>;
1019#endif
1020
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001021// Comparisons between optionals
Eric Fiselier8af90142017-03-30 20:06:52 +00001022template <class _Tp, class _Up>
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001023_LIBCPP_INLINE_VISIBILITY constexpr
1024enable_if_t<
1025 is_convertible_v<decltype(_VSTD::declval<const _Tp&>() ==
Eric Fiselier8af90142017-03-30 20:06:52 +00001026 _VSTD::declval<const _Up&>()), bool>,
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001027 bool
1028>
Eric Fiselier8af90142017-03-30 20:06:52 +00001029operator==(const optional<_Tp>& __x, const optional<_Up>& __y)
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001030{
1031 if (static_cast<bool>(__x) != static_cast<bool>(__y))
1032 return false;
1033 if (!static_cast<bool>(__x))
1034 return true;
1035 return *__x == *__y;
1036}
1037
Eric Fiselier8af90142017-03-30 20:06:52 +00001038template <class _Tp, class _Up>
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001039_LIBCPP_INLINE_VISIBILITY constexpr
1040enable_if_t<
1041 is_convertible_v<decltype(_VSTD::declval<const _Tp&>() !=
Eric Fiselier8af90142017-03-30 20:06:52 +00001042 _VSTD::declval<const _Up&>()), bool>,
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001043 bool
1044>
Eric Fiselier8af90142017-03-30 20:06:52 +00001045operator!=(const optional<_Tp>& __x, const optional<_Up>& __y)
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001046{
1047 if (static_cast<bool>(__x) != static_cast<bool>(__y))
1048 return true;
1049 if (!static_cast<bool>(__x))
1050 return false;
1051 return *__x != *__y;
1052}
1053
Eric Fiselier8af90142017-03-30 20:06:52 +00001054template <class _Tp, class _Up>
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001055_LIBCPP_INLINE_VISIBILITY constexpr
1056enable_if_t<
1057 is_convertible_v<decltype(_VSTD::declval<const _Tp&>() <
Eric Fiselier8af90142017-03-30 20:06:52 +00001058 _VSTD::declval<const _Up&>()), bool>,
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001059 bool
1060>
Eric Fiselier8af90142017-03-30 20:06:52 +00001061operator<(const optional<_Tp>& __x, const optional<_Up>& __y)
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001062{
1063 if (!static_cast<bool>(__y))
1064 return false;
1065 if (!static_cast<bool>(__x))
1066 return true;
1067 return *__x < *__y;
1068}
1069
Eric Fiselier8af90142017-03-30 20:06:52 +00001070template <class _Tp, class _Up>
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001071_LIBCPP_INLINE_VISIBILITY constexpr
1072enable_if_t<
1073 is_convertible_v<decltype(_VSTD::declval<const _Tp&>() >
Eric Fiselier8af90142017-03-30 20:06:52 +00001074 _VSTD::declval<const _Up&>()), bool>,
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001075 bool
1076>
Eric Fiselier8af90142017-03-30 20:06:52 +00001077operator>(const optional<_Tp>& __x, const optional<_Up>& __y)
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001078{
1079 if (!static_cast<bool>(__x))
1080 return false;
1081 if (!static_cast<bool>(__y))
1082 return true;
1083 return *__x > *__y;
1084}
1085
Eric Fiselier8af90142017-03-30 20:06:52 +00001086template <class _Tp, class _Up>
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001087_LIBCPP_INLINE_VISIBILITY constexpr
1088enable_if_t<
1089 is_convertible_v<decltype(_VSTD::declval<const _Tp&>() <=
Eric Fiselier8af90142017-03-30 20:06:52 +00001090 _VSTD::declval<const _Up&>()), bool>,
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001091 bool
1092>
Eric Fiselier8af90142017-03-30 20:06:52 +00001093operator<=(const optional<_Tp>& __x, const optional<_Up>& __y)
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001094{
1095 if (!static_cast<bool>(__x))
1096 return true;
1097 if (!static_cast<bool>(__y))
1098 return false;
1099 return *__x <= *__y;
1100}
1101
Eric Fiselier8af90142017-03-30 20:06:52 +00001102template <class _Tp, class _Up>
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001103_LIBCPP_INLINE_VISIBILITY constexpr
1104enable_if_t<
1105 is_convertible_v<decltype(_VSTD::declval<const _Tp&>() >=
Eric Fiselier8af90142017-03-30 20:06:52 +00001106 _VSTD::declval<const _Up&>()), bool>,
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001107 bool
1108>
Eric Fiselier8af90142017-03-30 20:06:52 +00001109operator>=(const optional<_Tp>& __x, const optional<_Up>& __y)
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001110{
1111 if (!static_cast<bool>(__y))
1112 return true;
1113 if (!static_cast<bool>(__x))
1114 return false;
1115 return *__x >= *__y;
1116}
1117
1118// Comparisons with nullopt
1119template <class _Tp>
1120_LIBCPP_INLINE_VISIBILITY constexpr
1121bool
1122operator==(const optional<_Tp>& __x, nullopt_t) noexcept
1123{
1124 return !static_cast<bool>(__x);
1125}
1126
1127template <class _Tp>
1128_LIBCPP_INLINE_VISIBILITY constexpr
1129bool
1130operator==(nullopt_t, const optional<_Tp>& __x) noexcept
1131{
1132 return !static_cast<bool>(__x);
1133}
1134
1135template <class _Tp>
1136_LIBCPP_INLINE_VISIBILITY constexpr
1137bool
1138operator!=(const optional<_Tp>& __x, nullopt_t) noexcept
1139{
1140 return static_cast<bool>(__x);
1141}
1142
1143template <class _Tp>
1144_LIBCPP_INLINE_VISIBILITY constexpr
1145bool
1146operator!=(nullopt_t, const optional<_Tp>& __x) noexcept
1147{
1148 return static_cast<bool>(__x);
1149}
1150
1151template <class _Tp>
1152_LIBCPP_INLINE_VISIBILITY constexpr
1153bool
1154operator<(const optional<_Tp>&, nullopt_t) noexcept
1155{
1156 return false;
1157}
1158
1159template <class _Tp>
1160_LIBCPP_INLINE_VISIBILITY constexpr
1161bool
1162operator<(nullopt_t, const optional<_Tp>& __x) noexcept
1163{
1164 return static_cast<bool>(__x);
1165}
1166
1167template <class _Tp>
1168_LIBCPP_INLINE_VISIBILITY constexpr
1169bool
1170operator<=(const optional<_Tp>& __x, nullopt_t) noexcept
1171{
1172 return !static_cast<bool>(__x);
1173}
1174
1175template <class _Tp>
1176_LIBCPP_INLINE_VISIBILITY constexpr
1177bool
Eric Fiselier6003c772016-12-23 23:37:52 +00001178operator<=(nullopt_t, const optional<_Tp>&) noexcept
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001179{
1180 return true;
1181}
1182
1183template <class _Tp>
1184_LIBCPP_INLINE_VISIBILITY constexpr
1185bool
1186operator>(const optional<_Tp>& __x, nullopt_t) noexcept
1187{
1188 return static_cast<bool>(__x);
1189}
1190
1191template <class _Tp>
1192_LIBCPP_INLINE_VISIBILITY constexpr
1193bool
Eric Fiselier6003c772016-12-23 23:37:52 +00001194operator>(nullopt_t, const optional<_Tp>&) noexcept
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001195{
1196 return false;
1197}
1198
1199template <class _Tp>
1200_LIBCPP_INLINE_VISIBILITY constexpr
1201bool
1202operator>=(const optional<_Tp>&, nullopt_t) noexcept
1203{
1204 return true;
1205}
1206
1207template <class _Tp>
1208_LIBCPP_INLINE_VISIBILITY constexpr
1209bool
1210operator>=(nullopt_t, const optional<_Tp>& __x) noexcept
1211{
1212 return !static_cast<bool>(__x);
1213}
1214
1215// Comparisons with T
Eric Fiselier8af90142017-03-30 20:06:52 +00001216template <class _Tp, class _Up>
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001217_LIBCPP_INLINE_VISIBILITY constexpr
1218enable_if_t<
1219 is_convertible_v<decltype(_VSTD::declval<const _Tp&>() ==
Eric Fiselier8af90142017-03-30 20:06:52 +00001220 _VSTD::declval<const _Up&>()), bool>,
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001221 bool
1222>
Eric Fiselier8af90142017-03-30 20:06:52 +00001223operator==(const optional<_Tp>& __x, const _Up& __v)
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001224{
1225 return static_cast<bool>(__x) ? *__x == __v : false;
1226}
1227
Eric Fiselier8af90142017-03-30 20:06:52 +00001228template <class _Tp, class _Up>
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001229_LIBCPP_INLINE_VISIBILITY constexpr
1230enable_if_t<
1231 is_convertible_v<decltype(_VSTD::declval<const _Tp&>() ==
Eric Fiselier8af90142017-03-30 20:06:52 +00001232 _VSTD::declval<const _Up&>()), bool>,
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001233 bool
1234>
Eric Fiselier8af90142017-03-30 20:06:52 +00001235operator==(const _Tp& __v, const optional<_Up>& __x)
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001236{
1237 return static_cast<bool>(__x) ? __v == *__x : false;
1238}
1239
Eric Fiselier8af90142017-03-30 20:06:52 +00001240template <class _Tp, class _Up>
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001241_LIBCPP_INLINE_VISIBILITY constexpr
1242enable_if_t<
1243 is_convertible_v<decltype(_VSTD::declval<const _Tp&>() !=
Eric Fiselier8af90142017-03-30 20:06:52 +00001244 _VSTD::declval<const _Up&>()), bool>,
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001245 bool
1246>
Eric Fiselier8af90142017-03-30 20:06:52 +00001247operator!=(const optional<_Tp>& __x, const _Up& __v)
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001248{
1249 return static_cast<bool>(__x) ? *__x != __v : true;
1250}
1251
Eric Fiselier8af90142017-03-30 20:06:52 +00001252template <class _Tp, class _Up>
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001253_LIBCPP_INLINE_VISIBILITY constexpr
1254enable_if_t<
1255 is_convertible_v<decltype(_VSTD::declval<const _Tp&>() !=
Eric Fiselier8af90142017-03-30 20:06:52 +00001256 _VSTD::declval<const _Up&>()), bool>,
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001257 bool
1258>
Eric Fiselier8af90142017-03-30 20:06:52 +00001259operator!=(const _Tp& __v, const optional<_Up>& __x)
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001260{
1261 return static_cast<bool>(__x) ? __v != *__x : true;
1262}
1263
Eric Fiselier8af90142017-03-30 20:06:52 +00001264template <class _Tp, class _Up>
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001265_LIBCPP_INLINE_VISIBILITY constexpr
1266enable_if_t<
1267 is_convertible_v<decltype(_VSTD::declval<const _Tp&>() <
Eric Fiselier8af90142017-03-30 20:06:52 +00001268 _VSTD::declval<const _Up&>()), bool>,
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001269 bool
1270>
Eric Fiselier8af90142017-03-30 20:06:52 +00001271operator<(const optional<_Tp>& __x, const _Up& __v)
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001272{
1273 return static_cast<bool>(__x) ? *__x < __v : true;
1274}
1275
Eric Fiselier8af90142017-03-30 20:06:52 +00001276template <class _Tp, class _Up>
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001277_LIBCPP_INLINE_VISIBILITY constexpr
1278enable_if_t<
1279 is_convertible_v<decltype(_VSTD::declval<const _Tp&>() <
Eric Fiselier8af90142017-03-30 20:06:52 +00001280 _VSTD::declval<const _Up&>()), bool>,
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001281 bool
1282>
Eric Fiselier8af90142017-03-30 20:06:52 +00001283operator<(const _Tp& __v, const optional<_Up>& __x)
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001284{
1285 return static_cast<bool>(__x) ? __v < *__x : false;
1286}
1287
Eric Fiselier8af90142017-03-30 20:06:52 +00001288template <class _Tp, class _Up>
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001289_LIBCPP_INLINE_VISIBILITY constexpr
1290enable_if_t<
1291 is_convertible_v<decltype(_VSTD::declval<const _Tp&>() <=
Eric Fiselier8af90142017-03-30 20:06:52 +00001292 _VSTD::declval<const _Up&>()), bool>,
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001293 bool
1294>
Eric Fiselier8af90142017-03-30 20:06:52 +00001295operator<=(const optional<_Tp>& __x, const _Up& __v)
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001296{
1297 return static_cast<bool>(__x) ? *__x <= __v : true;
1298}
1299
Eric Fiselier8af90142017-03-30 20:06:52 +00001300template <class _Tp, class _Up>
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001301_LIBCPP_INLINE_VISIBILITY constexpr
1302enable_if_t<
1303 is_convertible_v<decltype(_VSTD::declval<const _Tp&>() <=
Eric Fiselier8af90142017-03-30 20:06:52 +00001304 _VSTD::declval<const _Up&>()), bool>,
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001305 bool
1306>
Eric Fiselier8af90142017-03-30 20:06:52 +00001307operator<=(const _Tp& __v, const optional<_Up>& __x)
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001308{
1309 return static_cast<bool>(__x) ? __v <= *__x : false;
1310}
1311
Eric Fiselier8af90142017-03-30 20:06:52 +00001312template <class _Tp, class _Up>
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001313_LIBCPP_INLINE_VISIBILITY constexpr
1314enable_if_t<
1315 is_convertible_v<decltype(_VSTD::declval<const _Tp&>() >
Eric Fiselier8af90142017-03-30 20:06:52 +00001316 _VSTD::declval<const _Up&>()), bool>,
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001317 bool
1318>
Eric Fiselier8af90142017-03-30 20:06:52 +00001319operator>(const optional<_Tp>& __x, const _Up& __v)
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001320{
1321 return static_cast<bool>(__x) ? *__x > __v : false;
1322}
1323
Eric Fiselier8af90142017-03-30 20:06:52 +00001324template <class _Tp, class _Up>
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001325_LIBCPP_INLINE_VISIBILITY constexpr
1326enable_if_t<
1327 is_convertible_v<decltype(_VSTD::declval<const _Tp&>() >
Eric Fiselier8af90142017-03-30 20:06:52 +00001328 _VSTD::declval<const _Up&>()), bool>,
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001329 bool
1330>
Eric Fiselier8af90142017-03-30 20:06:52 +00001331operator>(const _Tp& __v, const optional<_Up>& __x)
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001332{
1333 return static_cast<bool>(__x) ? __v > *__x : true;
1334}
1335
Eric Fiselier8af90142017-03-30 20:06:52 +00001336template <class _Tp, class _Up>
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001337_LIBCPP_INLINE_VISIBILITY constexpr
1338enable_if_t<
1339 is_convertible_v<decltype(_VSTD::declval<const _Tp&>() >=
Eric Fiselier8af90142017-03-30 20:06:52 +00001340 _VSTD::declval<const _Up&>()), bool>,
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001341 bool
1342>
Eric Fiselier8af90142017-03-30 20:06:52 +00001343operator>=(const optional<_Tp>& __x, const _Up& __v)
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001344{
1345 return static_cast<bool>(__x) ? *__x >= __v : false;
1346}
1347
Eric Fiselier8af90142017-03-30 20:06:52 +00001348template <class _Tp, class _Up>
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001349_LIBCPP_INLINE_VISIBILITY constexpr
1350enable_if_t<
1351 is_convertible_v<decltype(_VSTD::declval<const _Tp&>() >=
Eric Fiselier8af90142017-03-30 20:06:52 +00001352 _VSTD::declval<const _Up&>()), bool>,
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001353 bool
1354>
Eric Fiselier8af90142017-03-30 20:06:52 +00001355operator>=(const _Tp& __v, const optional<_Up>& __x)
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001356{
1357 return static_cast<bool>(__x) ? __v >= *__x : true;
1358}
1359
1360
1361template <class _Tp>
1362inline _LIBCPP_INLINE_VISIBILITY
1363enable_if_t<
1364 is_move_constructible_v<_Tp> && is_swappable_v<_Tp>,
1365 void
1366>
1367swap(optional<_Tp>& __x, optional<_Tp>& __y) noexcept(noexcept(__x.swap(__y)))
1368{
1369 __x.swap(__y);
1370}
1371
1372template <class _Tp>
1373_LIBCPP_INLINE_VISIBILITY constexpr
1374optional<decay_t<_Tp>> make_optional(_Tp&& __v)
1375{
1376 return optional<decay_t<_Tp>>(_VSTD::forward<_Tp>(__v));
1377}
1378
1379template <class _Tp, class... _Args>
1380_LIBCPP_INLINE_VISIBILITY constexpr
1381optional<_Tp> make_optional(_Args&&... __args)
1382{
1383 return optional<_Tp>(in_place, _VSTD::forward<_Args>(__args)...);
1384}
1385
1386template <class _Tp, class _Up, class... _Args>
1387_LIBCPP_INLINE_VISIBILITY constexpr
1388optional<_Tp> make_optional(initializer_list<_Up> __il, _Args&&... __args)
1389{
1390 return optional<_Tp>(in_place, __il, _VSTD::forward<_Args>(__args)...);
1391}
1392
1393template <class _Tp>
Eric Fiselier698a97b2017-01-21 00:02:12 +00001394struct _LIBCPP_TEMPLATE_VIS hash<
1395 __enable_hash_helper<optional<_Tp>, remove_const_t<_Tp>>
1396>
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001397{
1398 typedef optional<_Tp> argument_type;
1399 typedef size_t result_type;
1400
1401 _LIBCPP_INLINE_VISIBILITY
Marshall Clow49036892017-03-23 02:40:28 +00001402 result_type operator()(const argument_type& __opt) const
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001403 {
Eric Fiselier698a97b2017-01-21 00:02:12 +00001404 return static_cast<bool>(__opt) ? hash<remove_const_t<_Tp>>()(*__opt) : 0;
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001405 }
1406};
1407
1408_LIBCPP_END_NAMESPACE_STD
1409
1410#endif // _LIBCPP_STD_VER > 14
1411
Eric Fiselierf4433a32017-05-31 22:07:49 +00001412_LIBCPP_POP_MACROS
1413
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001414#endif // _LIBCPP_OPTIONAL