blob: a76f8d18976eee861630b58b81dcb9162a7f5e12 [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>
159
160#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
161#pragma GCC system_header
162#endif
163
Eric Fiselierf4433a32017-05-31 22:07:49 +0000164_LIBCPP_PUSH_MACROS
165#include <__undef_macros>
166
167
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000168namespace std // purposefully not using versioning namespace
169{
170
171class _LIBCPP_EXCEPTION_ABI bad_optional_access
Marshall Clowa627d4a2017-02-05 20:06:38 +0000172 : public exception
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000173{
174public:
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000175 // Get the key function ~bad_optional_access() into the dylib
Marshall Clow53fc0372017-02-05 20:52:32 +0000176 virtual ~bad_optional_access() _NOEXCEPT;
Marshall Clowa627d4a2017-02-05 20:06:38 +0000177 virtual const char* what() const _NOEXCEPT;
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000178};
179
180} // std
181
182#if _LIBCPP_STD_VER > 14
183
184_LIBCPP_BEGIN_NAMESPACE_STD
185
186_LIBCPP_NORETURN
187inline _LIBCPP_INLINE_VISIBILITY
188void __throw_bad_optional_access() {
189#ifndef _LIBCPP_NO_EXCEPTIONS
190 throw bad_optional_access();
191#else
192 _VSTD::abort();
193#endif
194}
195
196struct nullopt_t
197{
198 struct __secret_tag { _LIBCPP_INLINE_VISIBILITY explicit __secret_tag() = default; };
199 _LIBCPP_INLINE_VISIBILITY constexpr explicit nullopt_t(__secret_tag, __secret_tag) noexcept {}
200};
201
Marshall Clowf1bf62f2018-01-02 17:17:01 +0000202_LIBCPP_INLINE_VAR constexpr nullopt_t nullopt{nullopt_t::__secret_tag{}, nullopt_t::__secret_tag{}};
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000203
204template <class _Tp, bool = is_trivially_destructible<_Tp>::value>
205struct __optional_destruct_base;
206
207template <class _Tp>
208struct __optional_destruct_base<_Tp, false>
209{
210 typedef _Tp value_type;
211 static_assert(is_object_v<value_type>,
212 "instantiation of optional with a non-object type is undefined behavior");
213 union
214 {
215 char __null_state_;
216 value_type __val_;
217 };
218 bool __engaged_;
219
220 _LIBCPP_INLINE_VISIBILITY
221 ~__optional_destruct_base()
222 {
223 if (__engaged_)
224 __val_.~value_type();
225 }
226
227 _LIBCPP_INLINE_VISIBILITY
228 constexpr __optional_destruct_base() noexcept
229 : __null_state_(),
230 __engaged_(false) {}
231
232 template <class... _Args>
233 _LIBCPP_INLINE_VISIBILITY
234 constexpr explicit __optional_destruct_base(in_place_t, _Args&&... __args)
235 : __val_(_VSTD::forward<_Args>(__args)...),
236 __engaged_(true) {}
237
238 _LIBCPP_INLINE_VISIBILITY
239 void reset() noexcept
240 {
241 if (__engaged_)
242 {
243 __val_.~value_type();
244 __engaged_ = false;
245 }
246 }
247};
248
249template <class _Tp>
250struct __optional_destruct_base<_Tp, true>
251{
252 typedef _Tp value_type;
253 static_assert(is_object_v<value_type>,
254 "instantiation of optional with a non-object type is undefined behavior");
255 union
256 {
257 char __null_state_;
258 value_type __val_;
259 };
260 bool __engaged_;
261
262 _LIBCPP_INLINE_VISIBILITY
263 constexpr __optional_destruct_base() noexcept
264 : __null_state_(),
265 __engaged_(false) {}
266
267 template <class... _Args>
268 _LIBCPP_INLINE_VISIBILITY
269 constexpr explicit __optional_destruct_base(in_place_t, _Args&&... __args)
270 : __val_(_VSTD::forward<_Args>(__args)...),
271 __engaged_(true) {}
272
273 _LIBCPP_INLINE_VISIBILITY
274 void reset() noexcept
275 {
276 if (__engaged_)
277 {
278 __engaged_ = false;
279 }
280 }
281};
282
283template <class _Tp, bool = is_reference<_Tp>::value>
284struct __optional_storage_base : __optional_destruct_base<_Tp>
285{
286 using __base = __optional_destruct_base<_Tp>;
287 using value_type = _Tp;
288 using __base::__base;
289
290 _LIBCPP_INLINE_VISIBILITY
291 constexpr bool has_value() const noexcept
292 {
293 return this->__engaged_;
294 }
295
296 _LIBCPP_INLINE_VISIBILITY
297 constexpr value_type& __get() & noexcept
298 {
299 return this->__val_;
300 }
301 _LIBCPP_INLINE_VISIBILITY
302 constexpr const value_type& __get() const& noexcept
303 {
304 return this->__val_;
305 }
306 _LIBCPP_INLINE_VISIBILITY
307 constexpr value_type&& __get() && noexcept
308 {
309 return _VSTD::move(this->__val_);
310 }
311 _LIBCPP_INLINE_VISIBILITY
312 constexpr const value_type&& __get() const&& noexcept
313 {
314 return _VSTD::move(this->__val_);
315 }
316
317 template <class... _Args>
318 _LIBCPP_INLINE_VISIBILITY
319 void __construct(_Args&&... __args)
320 {
321 _LIBCPP_ASSERT(!has_value(), "__construct called for engaged __optional_storage");
322 ::new((void*)_VSTD::addressof(this->__val_)) value_type(_VSTD::forward<_Args>(__args)...);
323 this->__engaged_ = true;
324 }
325
326 template <class _That>
327 _LIBCPP_INLINE_VISIBILITY
328 void __construct_from(_That&& __opt)
329 {
330 if (__opt.has_value())
331 __construct(_VSTD::forward<_That>(__opt).__get());
332 }
333
334 template <class _That>
335 _LIBCPP_INLINE_VISIBILITY
336 void __assign_from(_That&& __opt)
337 {
338 if (this->__engaged_ == __opt.has_value())
339 {
340 if (this->__engaged_)
341 this->__val_ = _VSTD::forward<_That>(__opt).__get();
342 }
343 else
344 {
345 if (this->__engaged_)
346 this->reset();
347 else
348 __construct(_VSTD::forward<_That>(__opt).__get());
349 }
350 }
351};
352
353// optional<T&> is currently required ill-formed, however it may to be in the
354// future. For this reason it has already been implemented to ensure we can
355// make the change in an ABI compatible manner.
356template <class _Tp>
357struct __optional_storage_base<_Tp, true>
358{
359 using value_type = _Tp;
360 using __raw_type = remove_reference_t<_Tp>;
361 __raw_type* __value_;
362
363 template <class _Up>
364 static constexpr bool __can_bind_reference() {
365 using _RawUp = typename remove_reference<_Up>::type;
366 using _UpPtr = _RawUp*;
367 using _RawTp = typename remove_reference<_Tp>::type;
368 using _TpPtr = _RawTp*;
369 using _CheckLValueArg = integral_constant<bool,
370 (is_lvalue_reference<_Up>::value && is_convertible<_UpPtr, _TpPtr>::value)
371 || is_same<_RawUp, reference_wrapper<_RawTp>>::value
372 || is_same<_RawUp, reference_wrapper<typename remove_const<_RawTp>::type>>::value
373 >;
374 return (is_lvalue_reference<_Tp>::value && _CheckLValueArg::value)
375 || (is_rvalue_reference<_Tp>::value && !is_lvalue_reference<_Up>::value &&
376 is_convertible<_UpPtr, _TpPtr>::value);
377 }
378
379 _LIBCPP_INLINE_VISIBILITY
380 constexpr __optional_storage_base() noexcept
381 : __value_(nullptr) {}
382
383 template <class _UArg>
384 _LIBCPP_INLINE_VISIBILITY
385 constexpr explicit __optional_storage_base(in_place_t, _UArg&& __uarg)
386 : __value_(_VSTD::addressof(__uarg))
387 {
388 static_assert(__can_bind_reference<_UArg>(),
389 "Attempted to construct a reference element in tuple from a "
390 "possible temporary");
391 }
392
393 _LIBCPP_INLINE_VISIBILITY
394 void reset() noexcept { __value_ = nullptr; }
395
396 _LIBCPP_INLINE_VISIBILITY
397 constexpr bool has_value() const noexcept
398 { return __value_ != nullptr; }
399
400 _LIBCPP_INLINE_VISIBILITY
401 constexpr value_type& __get() const& noexcept
402 { return *__value_; }
403
404 _LIBCPP_INLINE_VISIBILITY
405 constexpr value_type&& __get() const&& noexcept
406 { return _VSTD::forward<value_type>(*__value_); }
407
408 template <class _UArg>
409 _LIBCPP_INLINE_VISIBILITY
410 void __construct(_UArg&& __val)
411 {
412 _LIBCPP_ASSERT(!has_value(), "__construct called for engaged __optional_storage");
413 static_assert(__can_bind_reference<_UArg>(),
414 "Attempted to construct a reference element in tuple from a "
415 "possible temporary");
416 __value_ = _VSTD::addressof(__val);
417 }
418
419 template <class _That>
420 _LIBCPP_INLINE_VISIBILITY
421 void __construct_from(_That&& __opt)
422 {
423 if (__opt.has_value())
424 __construct(_VSTD::forward<_That>(__opt).__get());
425 }
426
427 template <class _That>
428 _LIBCPP_INLINE_VISIBILITY
429 void __assign_from(_That&& __opt)
430 {
431 if (has_value() == __opt.has_value())
432 {
433 if (has_value())
434 *__value_ = _VSTD::forward<_That>(__opt).__get();
435 }
436 else
437 {
438 if (has_value())
439 reset();
440 else
441 __construct(_VSTD::forward<_That>(__opt).__get());
442 }
443 }
444};
445
Casey Carterc189f7f2017-07-09 17:15:49 +0000446template <class _Tp, bool = is_trivially_copy_constructible<_Tp>::value>
447struct __optional_copy_base : __optional_storage_base<_Tp>
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000448{
449 using __optional_storage_base<_Tp>::__optional_storage_base;
450};
451
452template <class _Tp>
Casey Carterc189f7f2017-07-09 17:15:49 +0000453struct __optional_copy_base<_Tp, false> : __optional_storage_base<_Tp>
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000454{
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000455 using __optional_storage_base<_Tp>::__optional_storage_base;
456
457 _LIBCPP_INLINE_VISIBILITY
Casey Carterc189f7f2017-07-09 17:15:49 +0000458 __optional_copy_base() = default;
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000459
460 _LIBCPP_INLINE_VISIBILITY
Casey Carterc189f7f2017-07-09 17:15:49 +0000461 __optional_copy_base(const __optional_copy_base& __opt)
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000462 {
463 this->__construct_from(__opt);
464 }
465
466 _LIBCPP_INLINE_VISIBILITY
Casey Carterc189f7f2017-07-09 17:15:49 +0000467 __optional_copy_base(__optional_copy_base&&) = default;
468 _LIBCPP_INLINE_VISIBILITY
469 __optional_copy_base& operator=(const __optional_copy_base&) = default;
470 _LIBCPP_INLINE_VISIBILITY
471 __optional_copy_base& operator=(__optional_copy_base&&) = default;
472};
473
474template <class _Tp, bool = is_trivially_move_constructible<_Tp>::value>
475struct __optional_move_base : __optional_copy_base<_Tp>
476{
477 using __optional_copy_base<_Tp>::__optional_copy_base;
478};
479
480template <class _Tp>
481struct __optional_move_base<_Tp, false> : __optional_copy_base<_Tp>
482{
483 using value_type = _Tp;
484 using __optional_copy_base<_Tp>::__optional_copy_base;
485
486 _LIBCPP_INLINE_VISIBILITY
487 __optional_move_base() = default;
488 _LIBCPP_INLINE_VISIBILITY
489 __optional_move_base(const __optional_move_base&) = default;
490
491 _LIBCPP_INLINE_VISIBILITY
492 __optional_move_base(__optional_move_base&& __opt)
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000493 noexcept(is_nothrow_move_constructible_v<value_type>)
494 {
495 this->__construct_from(_VSTD::move(__opt));
496 }
497
498 _LIBCPP_INLINE_VISIBILITY
Casey Carterc189f7f2017-07-09 17:15:49 +0000499 __optional_move_base& operator=(const __optional_move_base&) = default;
500 _LIBCPP_INLINE_VISIBILITY
501 __optional_move_base& operator=(__optional_move_base&&) = default;
502};
503
504template <class _Tp, bool =
505 is_trivially_destructible<_Tp>::value &&
506 is_trivially_copy_constructible<_Tp>::value &&
507 is_trivially_copy_assignable<_Tp>::value>
508struct __optional_copy_assign_base : __optional_move_base<_Tp>
509{
510 using __optional_move_base<_Tp>::__optional_move_base;
511};
512
513template <class _Tp>
514struct __optional_copy_assign_base<_Tp, false> : __optional_move_base<_Tp>
515{
516 using __optional_move_base<_Tp>::__optional_move_base;
517
518 _LIBCPP_INLINE_VISIBILITY
519 __optional_copy_assign_base() = default;
520 _LIBCPP_INLINE_VISIBILITY
521 __optional_copy_assign_base(const __optional_copy_assign_base&) = default;
522 _LIBCPP_INLINE_VISIBILITY
523 __optional_copy_assign_base(__optional_copy_assign_base&&) = default;
524
525 _LIBCPP_INLINE_VISIBILITY
526 __optional_copy_assign_base& operator=(const __optional_copy_assign_base& __opt)
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000527 {
528 this->__assign_from(__opt);
529 return *this;
530 }
531
532 _LIBCPP_INLINE_VISIBILITY
Casey Carterc189f7f2017-07-09 17:15:49 +0000533 __optional_copy_assign_base& operator=(__optional_copy_assign_base&&) = default;
534};
535
536template <class _Tp, bool =
537 is_trivially_destructible<_Tp>::value &&
538 is_trivially_move_constructible<_Tp>::value &&
539 is_trivially_move_assignable<_Tp>::value>
540struct __optional_move_assign_base : __optional_copy_assign_base<_Tp>
541{
542 using __optional_copy_assign_base<_Tp>::__optional_copy_assign_base;
543};
544
545template <class _Tp>
546struct __optional_move_assign_base<_Tp, false> : __optional_copy_assign_base<_Tp>
547{
548 using value_type = _Tp;
549 using __optional_copy_assign_base<_Tp>::__optional_copy_assign_base;
550
551 _LIBCPP_INLINE_VISIBILITY
552 __optional_move_assign_base() = default;
553 _LIBCPP_INLINE_VISIBILITY
554 __optional_move_assign_base(const __optional_move_assign_base& __opt) = default;
555 _LIBCPP_INLINE_VISIBILITY
556 __optional_move_assign_base(__optional_move_assign_base&&) = default;
557 _LIBCPP_INLINE_VISIBILITY
558 __optional_move_assign_base& operator=(const __optional_move_assign_base&) = default;
559
560 _LIBCPP_INLINE_VISIBILITY
561 __optional_move_assign_base& operator=(__optional_move_assign_base&& __opt)
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000562 noexcept(is_nothrow_move_assignable_v<value_type> &&
563 is_nothrow_move_constructible_v<value_type>)
564 {
565 this->__assign_from(_VSTD::move(__opt));
566 return *this;
567 }
568};
569
570template <class _Tp>
571using __optional_sfinae_ctor_base_t = __sfinae_ctor_base<
572 is_copy_constructible<_Tp>::value,
573 is_move_constructible<_Tp>::value
574>;
575
576template <class _Tp>
577using __optional_sfinae_assign_base_t = __sfinae_assign_base<
578 (is_copy_constructible<_Tp>::value && is_copy_assignable<_Tp>::value),
579 (is_move_constructible<_Tp>::value && is_move_assignable<_Tp>::value)
580>;
581
582template <class _Tp>
583class optional
Casey Carterc189f7f2017-07-09 17:15:49 +0000584 : private __optional_move_assign_base<_Tp>
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000585 , private __optional_sfinae_ctor_base_t<_Tp>
586 , private __optional_sfinae_assign_base_t<_Tp>
587{
Casey Carterc189f7f2017-07-09 17:15:49 +0000588 using __base = __optional_move_assign_base<_Tp>;
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000589public:
590 using value_type = _Tp;
591
592private:
593 // Disable the reference extension using this static assert.
594 static_assert(!is_same_v<value_type, in_place_t>,
595 "instantiation of optional with in_place_t is ill-formed");
596 static_assert(!is_same_v<__uncvref_t<value_type>, nullopt_t>,
597 "instantiation of optional with nullopt_t is ill-formed");
598 static_assert(!is_reference_v<value_type>,
599 "instantiation of optional with a reference type is ill-formed");
600 static_assert(is_destructible_v<value_type>,
601 "instantiation of optional with a non-destructible type is ill-formed");
602
603 // LWG2756: conditionally explicit conversion from _Up
604 struct _CheckOptionalArgsConstructor {
605 template <class _Up>
606 static constexpr bool __enable_implicit() {
607 return is_constructible_v<_Tp, _Up&&> &&
608 is_convertible_v<_Up&&, _Tp>;
609 }
610
611 template <class _Up>
612 static constexpr bool __enable_explicit() {
613 return is_constructible_v<_Tp, _Up&&> &&
614 !is_convertible_v<_Up&&, _Tp>;
615 }
616 };
617 template <class _Up>
618 using _CheckOptionalArgsCtor = conditional_t<
Marshall Clowd5bbc242018-02-06 20:56:55 +0000619 !is_same_v<__uncvref_t<_Up>, in_place_t> &&
620 !is_same_v<__uncvref_t<_Up>, optional>,
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000621 _CheckOptionalArgsConstructor,
622 __check_tuple_constructor_fail
623 >;
624 template <class _QualUp>
625 struct _CheckOptionalLikeConstructor {
626 template <class _Up, class _Opt = optional<_Up>>
627 using __check_constructible_from_opt = __lazy_or<
628 is_constructible<_Tp, _Opt&>,
629 is_constructible<_Tp, _Opt const&>,
630 is_constructible<_Tp, _Opt&&>,
631 is_constructible<_Tp, _Opt const&&>,
632 is_convertible<_Opt&, _Tp>,
633 is_convertible<_Opt const&, _Tp>,
634 is_convertible<_Opt&&, _Tp>,
635 is_convertible<_Opt const&&, _Tp>
636 >;
637 template <class _Up, class _Opt = optional<_Up>>
638 using __check_assignable_from_opt = __lazy_or<
639 is_assignable<_Tp&, _Opt&>,
640 is_assignable<_Tp&, _Opt const&>,
641 is_assignable<_Tp&, _Opt&&>,
642 is_assignable<_Tp&, _Opt const&&>
643 >;
644 template <class _Up, class _QUp = _QualUp>
645 static constexpr bool __enable_implicit() {
646 return is_convertible<_QUp, _Tp>::value &&
647 !__check_constructible_from_opt<_Up>::value;
648 }
649 template <class _Up, class _QUp = _QualUp>
650 static constexpr bool __enable_explicit() {
651 return !is_convertible<_QUp, _Tp>::value &&
652 !__check_constructible_from_opt<_Up>::value;
653 }
654 template <class _Up, class _QUp = _QualUp>
655 static constexpr bool __enable_assign() {
656 // Construction and assignability of _Qup to _Tp has already been
657 // checked.
658 return !__check_constructible_from_opt<_Up>::value &&
659 !__check_assignable_from_opt<_Up>::value;
660 }
661 };
662
663 template <class _Up, class _QualUp>
664 using _CheckOptionalLikeCtor = conditional_t<
665 __lazy_and<
666 __lazy_not<is_same<_Up, _Tp>>,
667 is_constructible<_Tp, _QualUp>
668 >::value,
669 _CheckOptionalLikeConstructor<_QualUp>,
670 __check_tuple_constructor_fail
671 >;
672 template <class _Up, class _QualUp>
673 using _CheckOptionalLikeAssign = conditional_t<
674 __lazy_and<
675 __lazy_not<is_same<_Up, _Tp>>,
676 is_constructible<_Tp, _QualUp>,
677 is_assignable<_Tp&, _QualUp>
678 >::value,
679 _CheckOptionalLikeConstructor<_QualUp>,
680 __check_tuple_constructor_fail
681 >;
682public:
683
684 _LIBCPP_INLINE_VISIBILITY constexpr optional() noexcept {}
Marshall Clowd44e2e32017-05-17 15:30:01 +0000685 _LIBCPP_INLINE_VISIBILITY constexpr optional(const optional&) = default;
686 _LIBCPP_INLINE_VISIBILITY constexpr optional(optional&&) = default;
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000687 _LIBCPP_INLINE_VISIBILITY constexpr optional(nullopt_t) noexcept {}
688
689 template <class... _Args, class = enable_if_t<
690 is_constructible_v<value_type, _Args...>>
691 >
692 _LIBCPP_INLINE_VISIBILITY
693 constexpr explicit optional(in_place_t, _Args&&... __args)
694 : __base(in_place, _VSTD::forward<_Args>(__args)...) {}
695
696 template <class _Up, class... _Args, class = enable_if_t<
697 is_constructible_v<value_type, initializer_list<_Up>&, _Args...>>
698 >
699 _LIBCPP_INLINE_VISIBILITY
700 constexpr explicit optional(in_place_t, initializer_list<_Up> __il, _Args&&... __args)
701 : __base(in_place, __il, _VSTD::forward<_Args>(__args)...) {}
702
703 template <class _Up = value_type, enable_if_t<
704 _CheckOptionalArgsCtor<_Up>::template __enable_implicit<_Up>()
705 , int> = 0>
706 _LIBCPP_INLINE_VISIBILITY
707 constexpr optional(_Up&& __v)
708 : __base(in_place, _VSTD::forward<_Up>(__v)) {}
709
710 template <class _Up, enable_if_t<
711 _CheckOptionalArgsCtor<_Up>::template __enable_explicit<_Up>()
712 , int> = 0>
713 _LIBCPP_INLINE_VISIBILITY
714 constexpr explicit optional(_Up&& __v)
715 : __base(in_place, _VSTD::forward<_Up>(__v)) {}
716
717 // LWG2756: conditionally explicit conversion from const optional<_Up>&
718 template <class _Up, enable_if_t<
719 _CheckOptionalLikeCtor<_Up, _Up const&>::template __enable_implicit<_Up>()
720 , int> = 0>
721 _LIBCPP_INLINE_VISIBILITY
722 optional(const optional<_Up>& __v)
723 {
724 this->__construct_from(__v);
725 }
726 template <class _Up, enable_if_t<
727 _CheckOptionalLikeCtor<_Up, _Up const&>::template __enable_explicit<_Up>()
728 , int> = 0>
729 _LIBCPP_INLINE_VISIBILITY
730 explicit optional(const optional<_Up>& __v)
731 {
732 this->__construct_from(__v);
733 }
734
735 // LWG2756: conditionally explicit conversion from optional<_Up>&&
736 template <class _Up, enable_if_t<
737 _CheckOptionalLikeCtor<_Up, _Up &&>::template __enable_implicit<_Up>()
738 , int> = 0>
739 _LIBCPP_INLINE_VISIBILITY
740 optional(optional<_Up>&& __v)
741 {
742 this->__construct_from(_VSTD::move(__v));
743 }
744 template <class _Up, enable_if_t<
745 _CheckOptionalLikeCtor<_Up, _Up &&>::template __enable_explicit<_Up>()
746 , int> = 0>
747 _LIBCPP_INLINE_VISIBILITY
748 explicit optional(optional<_Up>&& __v)
749 {
750 this->__construct_from(_VSTD::move(__v));
751 }
752
753 _LIBCPP_INLINE_VISIBILITY
754 optional& operator=(nullopt_t) noexcept
755 {
756 reset();
757 return *this;
758 }
759
760 _LIBCPP_INLINE_VISIBILITY optional& operator=(const optional&) = default;
761 _LIBCPP_INLINE_VISIBILITY optional& operator=(optional&&) = default;
762
763 // LWG2756
764 template <class _Up = value_type,
765 class = enable_if_t
Eric Fiselierb9014262016-10-16 03:21:35 +0000766 <__lazy_and<
767 integral_constant<bool,
Marshall Clowd5bbc242018-02-06 20:56:55 +0000768 !is_same_v<__uncvref_t<_Up>, optional> &&
Eric Fiselierb9014262016-10-16 03:21:35 +0000769 !(is_same_v<_Up, value_type> && is_scalar_v<value_type>)
770 >,
771 is_constructible<value_type, _Up>,
772 is_assignable<value_type&, _Up>
773 >::value>
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000774 >
775 _LIBCPP_INLINE_VISIBILITY
776 optional&
777 operator=(_Up&& __v)
778 {
779 if (this->has_value())
780 this->__get() = _VSTD::forward<_Up>(__v);
781 else
782 this->__construct(_VSTD::forward<_Up>(__v));
783 return *this;
784 }
785
786 // LWG2756
787 template <class _Up, enable_if_t<
788 _CheckOptionalLikeAssign<_Up, _Up const&>::template __enable_assign<_Up>()
789 , int> = 0>
790 _LIBCPP_INLINE_VISIBILITY
791 optional&
792 operator=(const optional<_Up>& __v)
793 {
794 this->__assign_from(__v);
795 return *this;
796 }
797
798 // LWG2756
799 template <class _Up, enable_if_t<
800 _CheckOptionalLikeCtor<_Up, _Up &&>::template __enable_assign<_Up>()
801 , int> = 0>
802 _LIBCPP_INLINE_VISIBILITY
803 optional&
804 operator=(optional<_Up>&& __v)
805 {
806 this->__assign_from(_VSTD::move(__v));
807 return *this;
808 }
809
810 template <class... _Args,
811 class = enable_if_t
812 <
813 is_constructible_v<value_type, _Args...>
814 >
815 >
816 _LIBCPP_INLINE_VISIBILITY
Marshall Clow45ff9822017-04-12 22:51:27 +0000817 _Tp &
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000818 emplace(_Args&&... __args)
819 {
820 reset();
821 this->__construct(_VSTD::forward<_Args>(__args)...);
Marshall Clow45ff9822017-04-12 22:51:27 +0000822 return this->__get();
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000823 }
824
825 template <class _Up, class... _Args,
826 class = enable_if_t
827 <
828 is_constructible_v<value_type, initializer_list<_Up>&, _Args...>
829 >
830 >
831 _LIBCPP_INLINE_VISIBILITY
Marshall Clow45ff9822017-04-12 22:51:27 +0000832 _Tp &
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000833 emplace(initializer_list<_Up> __il, _Args&&... __args)
834 {
835 reset();
836 this->__construct(__il, _VSTD::forward<_Args>(__args)...);
Marshall Clow45ff9822017-04-12 22:51:27 +0000837 return this->__get();
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000838 }
839
840 _LIBCPP_INLINE_VISIBILITY
841 void swap(optional& __opt)
842 noexcept(is_nothrow_move_constructible_v<value_type> &&
843 is_nothrow_swappable_v<value_type>)
844 {
845 if (this->has_value() == __opt.has_value())
846 {
847 using _VSTD::swap;
848 if (this->has_value())
849 swap(this->__get(), __opt.__get());
850 }
851 else
852 {
853 if (this->has_value())
854 {
855 __opt.__construct(_VSTD::move(this->__get()));
856 reset();
857 }
858 else
859 {
860 this->__construct(_VSTD::move(__opt.__get()));
861 __opt.reset();
862 }
863 }
864 }
865
866 _LIBCPP_INLINE_VISIBILITY
867 constexpr
868 add_pointer_t<value_type const>
869 operator->() const
870 {
871 _LIBCPP_ASSERT(this->has_value(), "optional operator-> called for disengaged value");
872#ifndef _LIBCPP_HAS_NO_BUILTIN_ADDRESSOF
873 return _VSTD::addressof(this->__get());
874#else
875 return __operator_arrow(__has_operator_addressof<value_type>{}, this->__get());
876#endif
877 }
878
879 _LIBCPP_INLINE_VISIBILITY
880 constexpr
881 add_pointer_t<value_type>
882 operator->()
883 {
884 _LIBCPP_ASSERT(this->has_value(), "optional operator-> called for disengaged value");
885#ifndef _LIBCPP_HAS_NO_BUILTIN_ADDRESSOF
886 return _VSTD::addressof(this->__get());
887#else
888 return __operator_arrow(__has_operator_addressof<value_type>{}, this->__get());
889#endif
890 }
891
892 _LIBCPP_INLINE_VISIBILITY
893 constexpr
894 const value_type&
895 operator*() const&
896 {
897 _LIBCPP_ASSERT(this->has_value(), "optional operator* called for disengaged value");
898 return this->__get();
899 }
900
901 _LIBCPP_INLINE_VISIBILITY
902 constexpr
903 value_type&
904 operator*() &
905 {
906 _LIBCPP_ASSERT(this->has_value(), "optional operator* called for disengaged value");
907 return this->__get();
908 }
909
910 _LIBCPP_INLINE_VISIBILITY
911 constexpr
912 value_type&&
913 operator*() &&
914 {
915 _LIBCPP_ASSERT(this->has_value(), "optional operator* called for disengaged value");
916 return _VSTD::move(this->__get());
917 }
918
919 _LIBCPP_INLINE_VISIBILITY
920 constexpr
921 const value_type&&
922 operator*() const&&
923 {
924 _LIBCPP_ASSERT(this->has_value(), "optional operator* called for disengaged value");
925 return _VSTD::move(this->__get());
926 }
927
928 _LIBCPP_INLINE_VISIBILITY
929 constexpr explicit operator bool() const noexcept { return has_value(); }
930
931 using __base::has_value;
932 using __base::__get;
933
934 _LIBCPP_INLINE_VISIBILITY
935 constexpr value_type const& value() const&
936 {
937 if (!this->has_value())
938 __throw_bad_optional_access();
939 return this->__get();
940 }
941
942 _LIBCPP_INLINE_VISIBILITY
943 constexpr value_type& value() &
944 {
945 if (!this->has_value())
946 __throw_bad_optional_access();
947 return this->__get();
948 }
949
950 _LIBCPP_INLINE_VISIBILITY
951 constexpr value_type&& value() &&
952 {
953 if (!this->has_value())
954 __throw_bad_optional_access();
955 return _VSTD::move(this->__get());
956 }
957
958 _LIBCPP_INLINE_VISIBILITY
959 constexpr value_type const&& value() const&&
960 {
961 if (!this->has_value())
962 __throw_bad_optional_access();
963 return _VSTD::move(this->__get());
964 }
965
966 template <class _Up>
967 _LIBCPP_INLINE_VISIBILITY
968 constexpr value_type value_or(_Up&& __v) const&
969 {
970 static_assert(is_copy_constructible_v<value_type>,
971 "optional<T>::value_or: T must be copy constructible");
972 static_assert(is_convertible_v<_Up, value_type>,
973 "optional<T>::value_or: U must be convertible to T");
974 return this->has_value() ? this->__get() :
975 static_cast<value_type>(_VSTD::forward<_Up>(__v));
976 }
977
978 template <class _Up>
979 _LIBCPP_INLINE_VISIBILITY
Casey Cartercb05fae2017-06-06 18:47:26 +0000980 constexpr value_type value_or(_Up&& __v) &&
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000981 {
982 static_assert(is_move_constructible_v<value_type>,
983 "optional<T>::value_or: T must be move constructible");
984 static_assert(is_convertible_v<_Up, value_type>,
985 "optional<T>::value_or: U must be convertible to T");
986 return this->has_value() ? _VSTD::move(this->__get()) :
987 static_cast<value_type>(_VSTD::forward<_Up>(__v));
988 }
989
990 using __base::reset;
991
992private:
993 template <class _Up>
994 _LIBCPP_INLINE_VISIBILITY
995 static _Up*
996 __operator_arrow(true_type, _Up& __x)
997 {
998 return _VSTD::addressof(__x);
999 }
1000
1001 template <class _Up>
1002 _LIBCPP_INLINE_VISIBILITY
1003 static constexpr _Up*
1004 __operator_arrow(false_type, _Up& __x)
1005 {
1006 return &__x;
1007 }
1008};
1009
Marshall Clowe3c71ae2018-05-25 02:08:49 +00001010#ifndef _LIBCPP_HAS_NO_DEDUCTION_GUIDES
1011template<class T>
1012 optional(T) -> optional<T>;
1013#endif
1014
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001015// Comparisons between optionals
Eric Fiselier8af90142017-03-30 20:06:52 +00001016template <class _Tp, class _Up>
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001017_LIBCPP_INLINE_VISIBILITY constexpr
1018enable_if_t<
1019 is_convertible_v<decltype(_VSTD::declval<const _Tp&>() ==
Eric Fiselier8af90142017-03-30 20:06:52 +00001020 _VSTD::declval<const _Up&>()), bool>,
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001021 bool
1022>
Eric Fiselier8af90142017-03-30 20:06:52 +00001023operator==(const optional<_Tp>& __x, const optional<_Up>& __y)
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001024{
1025 if (static_cast<bool>(__x) != static_cast<bool>(__y))
1026 return false;
1027 if (!static_cast<bool>(__x))
1028 return true;
1029 return *__x == *__y;
1030}
1031
Eric Fiselier8af90142017-03-30 20:06:52 +00001032template <class _Tp, class _Up>
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001033_LIBCPP_INLINE_VISIBILITY constexpr
1034enable_if_t<
1035 is_convertible_v<decltype(_VSTD::declval<const _Tp&>() !=
Eric Fiselier8af90142017-03-30 20:06:52 +00001036 _VSTD::declval<const _Up&>()), bool>,
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001037 bool
1038>
Eric Fiselier8af90142017-03-30 20:06:52 +00001039operator!=(const optional<_Tp>& __x, const optional<_Up>& __y)
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001040{
1041 if (static_cast<bool>(__x) != static_cast<bool>(__y))
1042 return true;
1043 if (!static_cast<bool>(__x))
1044 return false;
1045 return *__x != *__y;
1046}
1047
Eric Fiselier8af90142017-03-30 20:06:52 +00001048template <class _Tp, class _Up>
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001049_LIBCPP_INLINE_VISIBILITY constexpr
1050enable_if_t<
1051 is_convertible_v<decltype(_VSTD::declval<const _Tp&>() <
Eric Fiselier8af90142017-03-30 20:06:52 +00001052 _VSTD::declval<const _Up&>()), bool>,
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001053 bool
1054>
Eric Fiselier8af90142017-03-30 20:06:52 +00001055operator<(const optional<_Tp>& __x, const optional<_Up>& __y)
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001056{
1057 if (!static_cast<bool>(__y))
1058 return false;
1059 if (!static_cast<bool>(__x))
1060 return true;
1061 return *__x < *__y;
1062}
1063
Eric Fiselier8af90142017-03-30 20:06:52 +00001064template <class _Tp, class _Up>
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001065_LIBCPP_INLINE_VISIBILITY constexpr
1066enable_if_t<
1067 is_convertible_v<decltype(_VSTD::declval<const _Tp&>() >
Eric Fiselier8af90142017-03-30 20:06:52 +00001068 _VSTD::declval<const _Up&>()), bool>,
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001069 bool
1070>
Eric Fiselier8af90142017-03-30 20:06:52 +00001071operator>(const optional<_Tp>& __x, const optional<_Up>& __y)
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001072{
1073 if (!static_cast<bool>(__x))
1074 return false;
1075 if (!static_cast<bool>(__y))
1076 return true;
1077 return *__x > *__y;
1078}
1079
Eric Fiselier8af90142017-03-30 20:06:52 +00001080template <class _Tp, class _Up>
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001081_LIBCPP_INLINE_VISIBILITY constexpr
1082enable_if_t<
1083 is_convertible_v<decltype(_VSTD::declval<const _Tp&>() <=
Eric Fiselier8af90142017-03-30 20:06:52 +00001084 _VSTD::declval<const _Up&>()), bool>,
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001085 bool
1086>
Eric Fiselier8af90142017-03-30 20:06:52 +00001087operator<=(const optional<_Tp>& __x, const optional<_Up>& __y)
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001088{
1089 if (!static_cast<bool>(__x))
1090 return true;
1091 if (!static_cast<bool>(__y))
1092 return false;
1093 return *__x <= *__y;
1094}
1095
Eric Fiselier8af90142017-03-30 20:06:52 +00001096template <class _Tp, class _Up>
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001097_LIBCPP_INLINE_VISIBILITY constexpr
1098enable_if_t<
1099 is_convertible_v<decltype(_VSTD::declval<const _Tp&>() >=
Eric Fiselier8af90142017-03-30 20:06:52 +00001100 _VSTD::declval<const _Up&>()), bool>,
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001101 bool
1102>
Eric Fiselier8af90142017-03-30 20:06:52 +00001103operator>=(const optional<_Tp>& __x, const optional<_Up>& __y)
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001104{
1105 if (!static_cast<bool>(__y))
1106 return true;
1107 if (!static_cast<bool>(__x))
1108 return false;
1109 return *__x >= *__y;
1110}
1111
1112// Comparisons with nullopt
1113template <class _Tp>
1114_LIBCPP_INLINE_VISIBILITY constexpr
1115bool
1116operator==(const optional<_Tp>& __x, nullopt_t) noexcept
1117{
1118 return !static_cast<bool>(__x);
1119}
1120
1121template <class _Tp>
1122_LIBCPP_INLINE_VISIBILITY constexpr
1123bool
1124operator==(nullopt_t, const optional<_Tp>& __x) noexcept
1125{
1126 return !static_cast<bool>(__x);
1127}
1128
1129template <class _Tp>
1130_LIBCPP_INLINE_VISIBILITY constexpr
1131bool
1132operator!=(const optional<_Tp>& __x, nullopt_t) noexcept
1133{
1134 return static_cast<bool>(__x);
1135}
1136
1137template <class _Tp>
1138_LIBCPP_INLINE_VISIBILITY constexpr
1139bool
1140operator!=(nullopt_t, const optional<_Tp>& __x) noexcept
1141{
1142 return static_cast<bool>(__x);
1143}
1144
1145template <class _Tp>
1146_LIBCPP_INLINE_VISIBILITY constexpr
1147bool
1148operator<(const optional<_Tp>&, nullopt_t) noexcept
1149{
1150 return false;
1151}
1152
1153template <class _Tp>
1154_LIBCPP_INLINE_VISIBILITY constexpr
1155bool
1156operator<(nullopt_t, const optional<_Tp>& __x) noexcept
1157{
1158 return static_cast<bool>(__x);
1159}
1160
1161template <class _Tp>
1162_LIBCPP_INLINE_VISIBILITY constexpr
1163bool
1164operator<=(const optional<_Tp>& __x, nullopt_t) noexcept
1165{
1166 return !static_cast<bool>(__x);
1167}
1168
1169template <class _Tp>
1170_LIBCPP_INLINE_VISIBILITY constexpr
1171bool
Eric Fiselier6003c772016-12-23 23:37:52 +00001172operator<=(nullopt_t, const optional<_Tp>&) noexcept
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001173{
1174 return true;
1175}
1176
1177template <class _Tp>
1178_LIBCPP_INLINE_VISIBILITY constexpr
1179bool
1180operator>(const optional<_Tp>& __x, nullopt_t) noexcept
1181{
1182 return static_cast<bool>(__x);
1183}
1184
1185template <class _Tp>
1186_LIBCPP_INLINE_VISIBILITY constexpr
1187bool
Eric Fiselier6003c772016-12-23 23:37:52 +00001188operator>(nullopt_t, const optional<_Tp>&) noexcept
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001189{
1190 return false;
1191}
1192
1193template <class _Tp>
1194_LIBCPP_INLINE_VISIBILITY constexpr
1195bool
1196operator>=(const optional<_Tp>&, nullopt_t) noexcept
1197{
1198 return true;
1199}
1200
1201template <class _Tp>
1202_LIBCPP_INLINE_VISIBILITY constexpr
1203bool
1204operator>=(nullopt_t, const optional<_Tp>& __x) noexcept
1205{
1206 return !static_cast<bool>(__x);
1207}
1208
1209// Comparisons with T
Eric Fiselier8af90142017-03-30 20:06:52 +00001210template <class _Tp, class _Up>
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001211_LIBCPP_INLINE_VISIBILITY constexpr
1212enable_if_t<
1213 is_convertible_v<decltype(_VSTD::declval<const _Tp&>() ==
Eric Fiselier8af90142017-03-30 20:06:52 +00001214 _VSTD::declval<const _Up&>()), bool>,
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001215 bool
1216>
Eric Fiselier8af90142017-03-30 20:06:52 +00001217operator==(const optional<_Tp>& __x, const _Up& __v)
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001218{
1219 return static_cast<bool>(__x) ? *__x == __v : false;
1220}
1221
Eric Fiselier8af90142017-03-30 20:06:52 +00001222template <class _Tp, class _Up>
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001223_LIBCPP_INLINE_VISIBILITY constexpr
1224enable_if_t<
1225 is_convertible_v<decltype(_VSTD::declval<const _Tp&>() ==
Eric Fiselier8af90142017-03-30 20:06:52 +00001226 _VSTD::declval<const _Up&>()), bool>,
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001227 bool
1228>
Eric Fiselier8af90142017-03-30 20:06:52 +00001229operator==(const _Tp& __v, const optional<_Up>& __x)
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001230{
1231 return static_cast<bool>(__x) ? __v == *__x : false;
1232}
1233
Eric Fiselier8af90142017-03-30 20:06:52 +00001234template <class _Tp, class _Up>
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001235_LIBCPP_INLINE_VISIBILITY constexpr
1236enable_if_t<
1237 is_convertible_v<decltype(_VSTD::declval<const _Tp&>() !=
Eric Fiselier8af90142017-03-30 20:06:52 +00001238 _VSTD::declval<const _Up&>()), bool>,
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001239 bool
1240>
Eric Fiselier8af90142017-03-30 20:06:52 +00001241operator!=(const optional<_Tp>& __x, const _Up& __v)
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001242{
1243 return static_cast<bool>(__x) ? *__x != __v : true;
1244}
1245
Eric Fiselier8af90142017-03-30 20:06:52 +00001246template <class _Tp, class _Up>
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001247_LIBCPP_INLINE_VISIBILITY constexpr
1248enable_if_t<
1249 is_convertible_v<decltype(_VSTD::declval<const _Tp&>() !=
Eric Fiselier8af90142017-03-30 20:06:52 +00001250 _VSTD::declval<const _Up&>()), bool>,
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001251 bool
1252>
Eric Fiselier8af90142017-03-30 20:06:52 +00001253operator!=(const _Tp& __v, const optional<_Up>& __x)
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001254{
1255 return static_cast<bool>(__x) ? __v != *__x : true;
1256}
1257
Eric Fiselier8af90142017-03-30 20:06:52 +00001258template <class _Tp, class _Up>
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001259_LIBCPP_INLINE_VISIBILITY constexpr
1260enable_if_t<
1261 is_convertible_v<decltype(_VSTD::declval<const _Tp&>() <
Eric Fiselier8af90142017-03-30 20:06:52 +00001262 _VSTD::declval<const _Up&>()), bool>,
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001263 bool
1264>
Eric Fiselier8af90142017-03-30 20:06:52 +00001265operator<(const optional<_Tp>& __x, const _Up& __v)
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001266{
1267 return static_cast<bool>(__x) ? *__x < __v : true;
1268}
1269
Eric Fiselier8af90142017-03-30 20:06:52 +00001270template <class _Tp, class _Up>
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001271_LIBCPP_INLINE_VISIBILITY constexpr
1272enable_if_t<
1273 is_convertible_v<decltype(_VSTD::declval<const _Tp&>() <
Eric Fiselier8af90142017-03-30 20:06:52 +00001274 _VSTD::declval<const _Up&>()), bool>,
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001275 bool
1276>
Eric Fiselier8af90142017-03-30 20:06:52 +00001277operator<(const _Tp& __v, const optional<_Up>& __x)
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001278{
1279 return static_cast<bool>(__x) ? __v < *__x : false;
1280}
1281
Eric Fiselier8af90142017-03-30 20:06:52 +00001282template <class _Tp, class _Up>
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001283_LIBCPP_INLINE_VISIBILITY constexpr
1284enable_if_t<
1285 is_convertible_v<decltype(_VSTD::declval<const _Tp&>() <=
Eric Fiselier8af90142017-03-30 20:06:52 +00001286 _VSTD::declval<const _Up&>()), bool>,
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001287 bool
1288>
Eric Fiselier8af90142017-03-30 20:06:52 +00001289operator<=(const optional<_Tp>& __x, const _Up& __v)
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001290{
1291 return static_cast<bool>(__x) ? *__x <= __v : true;
1292}
1293
Eric Fiselier8af90142017-03-30 20:06:52 +00001294template <class _Tp, class _Up>
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001295_LIBCPP_INLINE_VISIBILITY constexpr
1296enable_if_t<
1297 is_convertible_v<decltype(_VSTD::declval<const _Tp&>() <=
Eric Fiselier8af90142017-03-30 20:06:52 +00001298 _VSTD::declval<const _Up&>()), bool>,
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001299 bool
1300>
Eric Fiselier8af90142017-03-30 20:06:52 +00001301operator<=(const _Tp& __v, const optional<_Up>& __x)
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001302{
1303 return static_cast<bool>(__x) ? __v <= *__x : false;
1304}
1305
Eric Fiselier8af90142017-03-30 20:06:52 +00001306template <class _Tp, class _Up>
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001307_LIBCPP_INLINE_VISIBILITY constexpr
1308enable_if_t<
1309 is_convertible_v<decltype(_VSTD::declval<const _Tp&>() >
Eric Fiselier8af90142017-03-30 20:06:52 +00001310 _VSTD::declval<const _Up&>()), bool>,
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001311 bool
1312>
Eric Fiselier8af90142017-03-30 20:06:52 +00001313operator>(const optional<_Tp>& __x, const _Up& __v)
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001314{
1315 return static_cast<bool>(__x) ? *__x > __v : false;
1316}
1317
Eric Fiselier8af90142017-03-30 20:06:52 +00001318template <class _Tp, class _Up>
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001319_LIBCPP_INLINE_VISIBILITY constexpr
1320enable_if_t<
1321 is_convertible_v<decltype(_VSTD::declval<const _Tp&>() >
Eric Fiselier8af90142017-03-30 20:06:52 +00001322 _VSTD::declval<const _Up&>()), bool>,
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001323 bool
1324>
Eric Fiselier8af90142017-03-30 20:06:52 +00001325operator>(const _Tp& __v, const optional<_Up>& __x)
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001326{
1327 return static_cast<bool>(__x) ? __v > *__x : true;
1328}
1329
Eric Fiselier8af90142017-03-30 20:06:52 +00001330template <class _Tp, class _Up>
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001331_LIBCPP_INLINE_VISIBILITY constexpr
1332enable_if_t<
1333 is_convertible_v<decltype(_VSTD::declval<const _Tp&>() >=
Eric Fiselier8af90142017-03-30 20:06:52 +00001334 _VSTD::declval<const _Up&>()), bool>,
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001335 bool
1336>
Eric Fiselier8af90142017-03-30 20:06:52 +00001337operator>=(const optional<_Tp>& __x, const _Up& __v)
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001338{
1339 return static_cast<bool>(__x) ? *__x >= __v : false;
1340}
1341
Eric Fiselier8af90142017-03-30 20:06:52 +00001342template <class _Tp, class _Up>
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001343_LIBCPP_INLINE_VISIBILITY constexpr
1344enable_if_t<
1345 is_convertible_v<decltype(_VSTD::declval<const _Tp&>() >=
Eric Fiselier8af90142017-03-30 20:06:52 +00001346 _VSTD::declval<const _Up&>()), bool>,
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001347 bool
1348>
Eric Fiselier8af90142017-03-30 20:06:52 +00001349operator>=(const _Tp& __v, const optional<_Up>& __x)
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001350{
1351 return static_cast<bool>(__x) ? __v >= *__x : true;
1352}
1353
1354
1355template <class _Tp>
1356inline _LIBCPP_INLINE_VISIBILITY
1357enable_if_t<
1358 is_move_constructible_v<_Tp> && is_swappable_v<_Tp>,
1359 void
1360>
1361swap(optional<_Tp>& __x, optional<_Tp>& __y) noexcept(noexcept(__x.swap(__y)))
1362{
1363 __x.swap(__y);
1364}
1365
1366template <class _Tp>
1367_LIBCPP_INLINE_VISIBILITY constexpr
1368optional<decay_t<_Tp>> make_optional(_Tp&& __v)
1369{
1370 return optional<decay_t<_Tp>>(_VSTD::forward<_Tp>(__v));
1371}
1372
1373template <class _Tp, class... _Args>
1374_LIBCPP_INLINE_VISIBILITY constexpr
1375optional<_Tp> make_optional(_Args&&... __args)
1376{
1377 return optional<_Tp>(in_place, _VSTD::forward<_Args>(__args)...);
1378}
1379
1380template <class _Tp, class _Up, class... _Args>
1381_LIBCPP_INLINE_VISIBILITY constexpr
1382optional<_Tp> make_optional(initializer_list<_Up> __il, _Args&&... __args)
1383{
1384 return optional<_Tp>(in_place, __il, _VSTD::forward<_Args>(__args)...);
1385}
1386
1387template <class _Tp>
Eric Fiselier698a97b2017-01-21 00:02:12 +00001388struct _LIBCPP_TEMPLATE_VIS hash<
1389 __enable_hash_helper<optional<_Tp>, remove_const_t<_Tp>>
1390>
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001391{
1392 typedef optional<_Tp> argument_type;
1393 typedef size_t result_type;
1394
1395 _LIBCPP_INLINE_VISIBILITY
Marshall Clow49036892017-03-23 02:40:28 +00001396 result_type operator()(const argument_type& __opt) const
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001397 {
Eric Fiselier698a97b2017-01-21 00:02:12 +00001398 return static_cast<bool>(__opt) ? hash<remove_const_t<_Tp>>()(*__opt) : 0;
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001399 }
1400};
1401
1402_LIBCPP_END_NAMESPACE_STD
1403
1404#endif // _LIBCPP_STD_VER > 14
1405
Eric Fiselierf4433a32017-05-31 22:07:49 +00001406_LIBCPP_POP_MACROS
1407
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001408#endif // _LIBCPP_OPTIONAL