blob: 1fc752e6ff146a57f527d17f9c91419a9da202fe [file] [log] [blame]
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001// -*- C++ -*-
2//===-------------------------- optional ----------------------------------===//
3//
Chandler Carruthd2012102019-01-19 10:56:40 +00004// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5// See https://llvm.org/LICENSE.txt for license information.
6// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
Eric Fiselierd4ec6352016-10-12 07:46:20 +00007//
8//===----------------------------------------------------------------------===//
9
10#ifndef _LIBCPP_OPTIONAL
11#define _LIBCPP_OPTIONAL
12
13/*
14 optional synopsis
15
16// C++1z
17
18namespace std {
Casey Carter84b8a402017-04-17 20:15:16 +000019 // 23.6.3, optional for object types
Eric Fiselierd4ec6352016-10-12 07:46:20 +000020 template <class T> class optional;
21
Casey Carter84b8a402017-04-17 20:15:16 +000022 // 23.6.4, no-value state indicator
Eric Fiselierd4ec6352016-10-12 07:46:20 +000023 struct nullopt_t{see below };
Marshall Clowf1bf62f2018-01-02 17:17:01 +000024 inline constexpr nullopt_t nullopt(unspecified );
Eric Fiselierd4ec6352016-10-12 07:46:20 +000025
Casey Carter84b8a402017-04-17 20:15:16 +000026 // 23.6.5, class bad_optional_access
Eric Fiselierd4ec6352016-10-12 07:46:20 +000027 class bad_optional_access;
28
Casey Carter84b8a402017-04-17 20:15:16 +000029 // 23.6.6, relational operators
30 template <class T, class U>
31 constexpr bool operator==(const optional<T>&, const optional<U>&);
32 template <class T, class U>
33 constexpr bool operator!=(const optional<T>&, const optional<U>&);
34 template <class T, class U>
35 constexpr bool operator<(const optional<T>&, const optional<U>&);
36 template <class T, class U>
37 constexpr bool operator>(const optional<T>&, const optional<U>&);
38 template <class T, class U>
39 constexpr bool operator<=(const optional<T>&, const optional<U>&);
40 template <class T, class U>
41 constexpr bool operator>=(const optional<T>&, const optional<U>&);
42
43 // 23.6.7 comparison with nullopt
Eric Fiselierd4ec6352016-10-12 07:46:20 +000044 template <class T> constexpr bool operator==(const optional<T>&, nullopt_t) noexcept;
45 template <class T> constexpr bool operator==(nullopt_t, const optional<T>&) noexcept;
46 template <class T> constexpr bool operator!=(const optional<T>&, nullopt_t) noexcept;
47 template <class T> constexpr bool operator!=(nullopt_t, const optional<T>&) noexcept;
48 template <class T> constexpr bool operator<(const optional<T>&, nullopt_t) noexcept;
49 template <class T> constexpr bool operator<(nullopt_t, const optional<T>&) noexcept;
50 template <class T> constexpr bool operator<=(const optional<T>&, nullopt_t) noexcept;
51 template <class T> constexpr bool operator<=(nullopt_t, const optional<T>&) noexcept;
52 template <class T> constexpr bool operator>(const optional<T>&, nullopt_t) noexcept;
53 template <class T> constexpr bool operator>(nullopt_t, const optional<T>&) noexcept;
54 template <class T> constexpr bool operator>=(const optional<T>&, nullopt_t) noexcept;
55 template <class T> constexpr bool operator>=(nullopt_t, const optional<T>&) noexcept;
56
Casey Carter84b8a402017-04-17 20:15:16 +000057 // 23.6.8, comparison with T
58 template <class T, class U> constexpr bool operator==(const optional<T>&, const U&);
Marshall Clow29dd7e42017-11-01 01:27:25 +000059 template <class T, class U> constexpr bool operator==(const T&, const optional<U>&);
Casey Carter84b8a402017-04-17 20:15:16 +000060 template <class T, class U> constexpr bool operator!=(const optional<T>&, const U&);
Marshall Clow29dd7e42017-11-01 01:27:25 +000061 template <class T, class U> constexpr bool operator!=(const T&, const optional<U>&);
Casey Carter84b8a402017-04-17 20:15:16 +000062 template <class T, class U> constexpr bool operator<(const optional<T>&, const U&);
Marshall Clow29dd7e42017-11-01 01:27:25 +000063 template <class T, class U> constexpr bool operator<(const T&, const optional<U>&);
Casey Carter84b8a402017-04-17 20:15:16 +000064 template <class T, class U> constexpr bool operator<=(const optional<T>&, const U&);
Marshall Clow29dd7e42017-11-01 01:27:25 +000065 template <class T, class U> constexpr bool operator<=(const T&, const optional<U>&);
Casey Carter84b8a402017-04-17 20:15:16 +000066 template <class T, class U> constexpr bool operator>(const optional<T>&, const U&);
Marshall Clow29dd7e42017-11-01 01:27:25 +000067 template <class T, class U> constexpr bool operator>(const T&, const optional<U>&);
Casey Carter84b8a402017-04-17 20:15:16 +000068 template <class T, class U> constexpr bool operator>=(const optional<T>&, const U&);
Marshall Clow29dd7e42017-11-01 01:27:25 +000069 template <class T, class U> constexpr bool operator>=(const T&, const optional<U>&);
Eric Fiselierd4ec6352016-10-12 07:46:20 +000070
Casey Carter84b8a402017-04-17 20:15:16 +000071 // 23.6.9, specialized algorithms
Eric Fiselierd4ec6352016-10-12 07:46:20 +000072 template <class T> void swap(optional<T>&, optional<T>&) noexcept(see below );
73 template <class T> constexpr optional<see below > make_optional(T&&);
74 template <class T, class... Args>
75 constexpr optional<T> make_optional(Args&&... args);
76 template <class T, class U, class... Args>
77 constexpr optional<T> make_optional(initializer_list<U> il, Args&&... args);
78
Casey Carter84b8a402017-04-17 20:15:16 +000079 // 23.6.10, hash support
Eric Fiselierd4ec6352016-10-12 07:46:20 +000080 template <class T> struct hash;
81 template <class T> struct hash<optional<T>>;
82
83 template <class T> class optional {
84 public:
85 using value_type = T;
86
Casey Carter84b8a402017-04-17 20:15:16 +000087 // 23.6.3.1, constructors
Eric Fiselierd4ec6352016-10-12 07:46:20 +000088 constexpr optional() noexcept;
89 constexpr optional(nullopt_t) noexcept;
90 optional(const optional &);
Marshall Clow45ff9822017-04-12 22:51:27 +000091 optional(optional &&) noexcept(see below);
Eric Fiselierd4ec6352016-10-12 07:46:20 +000092 template <class... Args> constexpr explicit optional(in_place_t, Args &&...);
93 template <class U, class... Args>
94 constexpr explicit optional(in_place_t, initializer_list<U>, Args &&...);
95 template <class U = T>
96 constexpr EXPLICIT optional(U &&);
97 template <class U>
98 constexpr EXPLICIT optional(const optional<U> &);
99 template <class U>
100 constexpr EXPLICIT optional(optional<U> &&);
101
Casey Carter84b8a402017-04-17 20:15:16 +0000102 // 23.6.3.2, destructor
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000103 ~optional();
104
Casey Carter84b8a402017-04-17 20:15:16 +0000105 // 23.6.3.3, assignment
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000106 optional &operator=(nullopt_t) noexcept;
Louis Dionnecee59012019-01-10 20:06:11 +0000107 optional &operator=(const optional &); // constexpr in C++20
108 optional &operator=(optional &&) noexcept(see below); // constexpr in C++20
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000109 template <class U = T> optional &operator=(U &&);
110 template <class U> optional &operator=(const optional<U> &);
111 template <class U> optional &operator=(optional<U> &&);
Marshall Clow45ff9822017-04-12 22:51:27 +0000112 template <class... Args> T& emplace(Args &&...);
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000113 template <class U, class... Args>
Marshall Clow45ff9822017-04-12 22:51:27 +0000114 T& emplace(initializer_list<U>, Args &&...);
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000115
Casey Carter84b8a402017-04-17 20:15:16 +0000116 // 23.6.3.4, swap
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000117 void swap(optional &) noexcept(see below );
118
Casey Carter84b8a402017-04-17 20:15:16 +0000119 // 23.6.3.5, observers
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000120 constexpr T const *operator->() const;
121 constexpr T *operator->();
122 constexpr T const &operator*() const &;
123 constexpr T &operator*() &;
124 constexpr T &&operator*() &&;
125 constexpr const T &&operator*() const &&;
126 constexpr explicit operator bool() const noexcept;
127 constexpr bool has_value() const noexcept;
128 constexpr T const &value() const &;
129 constexpr T &value() &;
130 constexpr T &&value() &&;
131 constexpr const T &&value() const &&;
132 template <class U> constexpr T value_or(U &&) const &;
133 template <class U> constexpr T value_or(U &&) &&;
134
Casey Carter84b8a402017-04-17 20:15:16 +0000135 // 23.6.3.6, modifiers
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000136 void reset() noexcept;
137
138 private:
139 T *val; // exposition only
140 };
Marshall Clowe3c71ae2018-05-25 02:08:49 +0000141
142template<class T>
143 optional(T) -> optional<T>;
144
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000145} // namespace std
146
147*/
148
149#include <__config>
150#include <__debug>
151#include <__functional_base>
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000152#include <functional>
153#include <initializer_list>
154#include <new>
155#include <stdexcept>
156#include <type_traits>
157#include <utility>
Marshall Clow0a1e7502018-09-12 19:41:40 +0000158#include <version>
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000159
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
Louis Dionnecef92e62018-11-19 15:37:04 +0000171class _LIBCPP_EXCEPTION_ABI _LIBCPP_AVAILABILITY_BAD_OPTIONAL_ACCESS 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
Louis Dionnecef92e62018-11-19 15:37:04 +0000188_LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000189void __throw_bad_optional_access() {
190#ifndef _LIBCPP_NO_EXCEPTIONS
191 throw bad_optional_access();
192#else
193 _VSTD::abort();
194#endif
195}
196
197struct nullopt_t
198{
199 struct __secret_tag { _LIBCPP_INLINE_VISIBILITY explicit __secret_tag() = default; };
200 _LIBCPP_INLINE_VISIBILITY constexpr explicit nullopt_t(__secret_tag, __secret_tag) noexcept {}
201};
202
Marshall Clowf1bf62f2018-01-02 17:17:01 +0000203_LIBCPP_INLINE_VAR constexpr nullopt_t nullopt{nullopt_t::__secret_tag{}, nullopt_t::__secret_tag{}};
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000204
205template <class _Tp, bool = is_trivially_destructible<_Tp>::value>
206struct __optional_destruct_base;
207
208template <class _Tp>
209struct __optional_destruct_base<_Tp, false>
210{
211 typedef _Tp value_type;
212 static_assert(is_object_v<value_type>,
213 "instantiation of optional with a non-object type is undefined behavior");
214 union
215 {
216 char __null_state_;
217 value_type __val_;
218 };
219 bool __engaged_;
220
221 _LIBCPP_INLINE_VISIBILITY
222 ~__optional_destruct_base()
223 {
224 if (__engaged_)
225 __val_.~value_type();
226 }
227
228 _LIBCPP_INLINE_VISIBILITY
229 constexpr __optional_destruct_base() noexcept
230 : __null_state_(),
231 __engaged_(false) {}
232
233 template <class... _Args>
234 _LIBCPP_INLINE_VISIBILITY
235 constexpr explicit __optional_destruct_base(in_place_t, _Args&&... __args)
236 : __val_(_VSTD::forward<_Args>(__args)...),
237 __engaged_(true) {}
238
239 _LIBCPP_INLINE_VISIBILITY
240 void reset() noexcept
241 {
242 if (__engaged_)
243 {
244 __val_.~value_type();
245 __engaged_ = false;
246 }
247 }
248};
249
250template <class _Tp>
251struct __optional_destruct_base<_Tp, true>
252{
253 typedef _Tp value_type;
254 static_assert(is_object_v<value_type>,
255 "instantiation of optional with a non-object type is undefined behavior");
256 union
257 {
258 char __null_state_;
259 value_type __val_;
260 };
261 bool __engaged_;
262
263 _LIBCPP_INLINE_VISIBILITY
264 constexpr __optional_destruct_base() noexcept
265 : __null_state_(),
266 __engaged_(false) {}
267
268 template <class... _Args>
269 _LIBCPP_INLINE_VISIBILITY
270 constexpr explicit __optional_destruct_base(in_place_t, _Args&&... __args)
271 : __val_(_VSTD::forward<_Args>(__args)...),
272 __engaged_(true) {}
273
274 _LIBCPP_INLINE_VISIBILITY
275 void reset() noexcept
276 {
277 if (__engaged_)
278 {
279 __engaged_ = false;
280 }
281 }
282};
283
284template <class _Tp, bool = is_reference<_Tp>::value>
285struct __optional_storage_base : __optional_destruct_base<_Tp>
286{
287 using __base = __optional_destruct_base<_Tp>;
288 using value_type = _Tp;
289 using __base::__base;
290
291 _LIBCPP_INLINE_VISIBILITY
292 constexpr bool has_value() const noexcept
293 {
294 return this->__engaged_;
295 }
296
297 _LIBCPP_INLINE_VISIBILITY
298 constexpr value_type& __get() & noexcept
299 {
300 return this->__val_;
301 }
302 _LIBCPP_INLINE_VISIBILITY
303 constexpr const value_type& __get() const& noexcept
304 {
305 return this->__val_;
306 }
307 _LIBCPP_INLINE_VISIBILITY
308 constexpr value_type&& __get() && noexcept
309 {
310 return _VSTD::move(this->__val_);
311 }
312 _LIBCPP_INLINE_VISIBILITY
313 constexpr const value_type&& __get() const&& noexcept
314 {
315 return _VSTD::move(this->__val_);
316 }
317
318 template <class... _Args>
319 _LIBCPP_INLINE_VISIBILITY
320 void __construct(_Args&&... __args)
321 {
322 _LIBCPP_ASSERT(!has_value(), "__construct called for engaged __optional_storage");
323 ::new((void*)_VSTD::addressof(this->__val_)) value_type(_VSTD::forward<_Args>(__args)...);
324 this->__engaged_ = true;
325 }
326
327 template <class _That>
328 _LIBCPP_INLINE_VISIBILITY
329 void __construct_from(_That&& __opt)
330 {
331 if (__opt.has_value())
332 __construct(_VSTD::forward<_That>(__opt).__get());
333 }
334
335 template <class _That>
336 _LIBCPP_INLINE_VISIBILITY
337 void __assign_from(_That&& __opt)
338 {
339 if (this->__engaged_ == __opt.has_value())
340 {
341 if (this->__engaged_)
342 this->__val_ = _VSTD::forward<_That>(__opt).__get();
343 }
344 else
345 {
346 if (this->__engaged_)
347 this->reset();
348 else
349 __construct(_VSTD::forward<_That>(__opt).__get());
350 }
351 }
352};
353
354// optional<T&> is currently required ill-formed, however it may to be in the
355// future. For this reason it has already been implemented to ensure we can
356// make the change in an ABI compatible manner.
357template <class _Tp>
358struct __optional_storage_base<_Tp, true>
359{
360 using value_type = _Tp;
361 using __raw_type = remove_reference_t<_Tp>;
362 __raw_type* __value_;
363
364 template <class _Up>
365 static constexpr bool __can_bind_reference() {
366 using _RawUp = typename remove_reference<_Up>::type;
367 using _UpPtr = _RawUp*;
368 using _RawTp = typename remove_reference<_Tp>::type;
369 using _TpPtr = _RawTp*;
370 using _CheckLValueArg = integral_constant<bool,
371 (is_lvalue_reference<_Up>::value && is_convertible<_UpPtr, _TpPtr>::value)
372 || is_same<_RawUp, reference_wrapper<_RawTp>>::value
373 || is_same<_RawUp, reference_wrapper<typename remove_const<_RawTp>::type>>::value
374 >;
375 return (is_lvalue_reference<_Tp>::value && _CheckLValueArg::value)
376 || (is_rvalue_reference<_Tp>::value && !is_lvalue_reference<_Up>::value &&
377 is_convertible<_UpPtr, _TpPtr>::value);
378 }
379
380 _LIBCPP_INLINE_VISIBILITY
381 constexpr __optional_storage_base() noexcept
382 : __value_(nullptr) {}
383
384 template <class _UArg>
385 _LIBCPP_INLINE_VISIBILITY
386 constexpr explicit __optional_storage_base(in_place_t, _UArg&& __uarg)
387 : __value_(_VSTD::addressof(__uarg))
388 {
389 static_assert(__can_bind_reference<_UArg>(),
390 "Attempted to construct a reference element in tuple from a "
391 "possible temporary");
392 }
393
394 _LIBCPP_INLINE_VISIBILITY
395 void reset() noexcept { __value_ = nullptr; }
396
397 _LIBCPP_INLINE_VISIBILITY
398 constexpr bool has_value() const noexcept
399 { return __value_ != nullptr; }
400
401 _LIBCPP_INLINE_VISIBILITY
402 constexpr value_type& __get() const& noexcept
403 { return *__value_; }
404
405 _LIBCPP_INLINE_VISIBILITY
406 constexpr value_type&& __get() const&& noexcept
407 { return _VSTD::forward<value_type>(*__value_); }
408
409 template <class _UArg>
410 _LIBCPP_INLINE_VISIBILITY
411 void __construct(_UArg&& __val)
412 {
413 _LIBCPP_ASSERT(!has_value(), "__construct called for engaged __optional_storage");
414 static_assert(__can_bind_reference<_UArg>(),
415 "Attempted to construct a reference element in tuple from a "
416 "possible temporary");
417 __value_ = _VSTD::addressof(__val);
418 }
419
420 template <class _That>
421 _LIBCPP_INLINE_VISIBILITY
422 void __construct_from(_That&& __opt)
423 {
424 if (__opt.has_value())
425 __construct(_VSTD::forward<_That>(__opt).__get());
426 }
427
428 template <class _That>
429 _LIBCPP_INLINE_VISIBILITY
430 void __assign_from(_That&& __opt)
431 {
432 if (has_value() == __opt.has_value())
433 {
434 if (has_value())
435 *__value_ = _VSTD::forward<_That>(__opt).__get();
436 }
437 else
438 {
439 if (has_value())
440 reset();
441 else
442 __construct(_VSTD::forward<_That>(__opt).__get());
443 }
444 }
445};
446
Casey Carterc189f7f2017-07-09 17:15:49 +0000447template <class _Tp, bool = is_trivially_copy_constructible<_Tp>::value>
448struct __optional_copy_base : __optional_storage_base<_Tp>
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000449{
450 using __optional_storage_base<_Tp>::__optional_storage_base;
451};
452
453template <class _Tp>
Casey Carterc189f7f2017-07-09 17:15:49 +0000454struct __optional_copy_base<_Tp, false> : __optional_storage_base<_Tp>
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000455{
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000456 using __optional_storage_base<_Tp>::__optional_storage_base;
457
458 _LIBCPP_INLINE_VISIBILITY
Casey Carterc189f7f2017-07-09 17:15:49 +0000459 __optional_copy_base() = default;
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000460
461 _LIBCPP_INLINE_VISIBILITY
Casey Carterc189f7f2017-07-09 17:15:49 +0000462 __optional_copy_base(const __optional_copy_base& __opt)
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000463 {
464 this->__construct_from(__opt);
465 }
466
467 _LIBCPP_INLINE_VISIBILITY
Casey Carterc189f7f2017-07-09 17:15:49 +0000468 __optional_copy_base(__optional_copy_base&&) = default;
469 _LIBCPP_INLINE_VISIBILITY
470 __optional_copy_base& operator=(const __optional_copy_base&) = default;
471 _LIBCPP_INLINE_VISIBILITY
472 __optional_copy_base& operator=(__optional_copy_base&&) = default;
473};
474
475template <class _Tp, bool = is_trivially_move_constructible<_Tp>::value>
476struct __optional_move_base : __optional_copy_base<_Tp>
477{
478 using __optional_copy_base<_Tp>::__optional_copy_base;
479};
480
481template <class _Tp>
482struct __optional_move_base<_Tp, false> : __optional_copy_base<_Tp>
483{
484 using value_type = _Tp;
485 using __optional_copy_base<_Tp>::__optional_copy_base;
486
487 _LIBCPP_INLINE_VISIBILITY
488 __optional_move_base() = default;
489 _LIBCPP_INLINE_VISIBILITY
490 __optional_move_base(const __optional_move_base&) = default;
491
492 _LIBCPP_INLINE_VISIBILITY
493 __optional_move_base(__optional_move_base&& __opt)
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000494 noexcept(is_nothrow_move_constructible_v<value_type>)
495 {
496 this->__construct_from(_VSTD::move(__opt));
497 }
498
499 _LIBCPP_INLINE_VISIBILITY
Casey Carterc189f7f2017-07-09 17:15:49 +0000500 __optional_move_base& operator=(const __optional_move_base&) = default;
501 _LIBCPP_INLINE_VISIBILITY
502 __optional_move_base& operator=(__optional_move_base&&) = default;
503};
504
505template <class _Tp, bool =
506 is_trivially_destructible<_Tp>::value &&
507 is_trivially_copy_constructible<_Tp>::value &&
508 is_trivially_copy_assignable<_Tp>::value>
509struct __optional_copy_assign_base : __optional_move_base<_Tp>
510{
511 using __optional_move_base<_Tp>::__optional_move_base;
512};
513
514template <class _Tp>
515struct __optional_copy_assign_base<_Tp, false> : __optional_move_base<_Tp>
516{
517 using __optional_move_base<_Tp>::__optional_move_base;
518
519 _LIBCPP_INLINE_VISIBILITY
520 __optional_copy_assign_base() = default;
521 _LIBCPP_INLINE_VISIBILITY
522 __optional_copy_assign_base(const __optional_copy_assign_base&) = default;
523 _LIBCPP_INLINE_VISIBILITY
524 __optional_copy_assign_base(__optional_copy_assign_base&&) = default;
525
526 _LIBCPP_INLINE_VISIBILITY
527 __optional_copy_assign_base& operator=(const __optional_copy_assign_base& __opt)
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000528 {
529 this->__assign_from(__opt);
530 return *this;
531 }
532
533 _LIBCPP_INLINE_VISIBILITY
Casey Carterc189f7f2017-07-09 17:15:49 +0000534 __optional_copy_assign_base& operator=(__optional_copy_assign_base&&) = default;
535};
536
537template <class _Tp, bool =
538 is_trivially_destructible<_Tp>::value &&
539 is_trivially_move_constructible<_Tp>::value &&
540 is_trivially_move_assignable<_Tp>::value>
541struct __optional_move_assign_base : __optional_copy_assign_base<_Tp>
542{
543 using __optional_copy_assign_base<_Tp>::__optional_copy_assign_base;
544};
545
546template <class _Tp>
547struct __optional_move_assign_base<_Tp, false> : __optional_copy_assign_base<_Tp>
548{
549 using value_type = _Tp;
550 using __optional_copy_assign_base<_Tp>::__optional_copy_assign_base;
551
552 _LIBCPP_INLINE_VISIBILITY
553 __optional_move_assign_base() = default;
554 _LIBCPP_INLINE_VISIBILITY
555 __optional_move_assign_base(const __optional_move_assign_base& __opt) = default;
556 _LIBCPP_INLINE_VISIBILITY
557 __optional_move_assign_base(__optional_move_assign_base&&) = default;
558 _LIBCPP_INLINE_VISIBILITY
559 __optional_move_assign_base& operator=(const __optional_move_assign_base&) = default;
560
561 _LIBCPP_INLINE_VISIBILITY
562 __optional_move_assign_base& operator=(__optional_move_assign_base&& __opt)
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000563 noexcept(is_nothrow_move_assignable_v<value_type> &&
564 is_nothrow_move_constructible_v<value_type>)
565 {
566 this->__assign_from(_VSTD::move(__opt));
567 return *this;
568 }
569};
570
571template <class _Tp>
572using __optional_sfinae_ctor_base_t = __sfinae_ctor_base<
573 is_copy_constructible<_Tp>::value,
574 is_move_constructible<_Tp>::value
575>;
576
577template <class _Tp>
578using __optional_sfinae_assign_base_t = __sfinae_assign_base<
579 (is_copy_constructible<_Tp>::value && is_copy_assignable<_Tp>::value),
580 (is_move_constructible<_Tp>::value && is_move_assignable<_Tp>::value)
581>;
582
583template <class _Tp>
584class optional
Casey Carterc189f7f2017-07-09 17:15:49 +0000585 : private __optional_move_assign_base<_Tp>
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000586 , private __optional_sfinae_ctor_base_t<_Tp>
587 , private __optional_sfinae_assign_base_t<_Tp>
588{
Casey Carterc189f7f2017-07-09 17:15:49 +0000589 using __base = __optional_move_assign_base<_Tp>;
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000590public:
591 using value_type = _Tp;
592
593private:
594 // Disable the reference extension using this static assert.
Marshall Clowfa6a3342019-03-25 16:35:59 +0000595 static_assert(!is_same_v<__uncvref_t<value_type>, in_place_t>,
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000596 "instantiation of optional with in_place_t is ill-formed");
597 static_assert(!is_same_v<__uncvref_t<value_type>, nullopt_t>,
598 "instantiation of optional with nullopt_t is ill-formed");
599 static_assert(!is_reference_v<value_type>,
600 "instantiation of optional with a reference type is ill-formed");
601 static_assert(is_destructible_v<value_type>,
602 "instantiation of optional with a non-destructible type is ill-formed");
Marshall Clowfa6a3342019-03-25 16:35:59 +0000603 static_assert(!is_array_v<value_type>,
604 "instantiation of optional with an array type is ill-formed");
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000605
606 // LWG2756: conditionally explicit conversion from _Up
607 struct _CheckOptionalArgsConstructor {
608 template <class _Up>
609 static constexpr bool __enable_implicit() {
610 return is_constructible_v<_Tp, _Up&&> &&
611 is_convertible_v<_Up&&, _Tp>;
612 }
613
614 template <class _Up>
615 static constexpr bool __enable_explicit() {
616 return is_constructible_v<_Tp, _Up&&> &&
617 !is_convertible_v<_Up&&, _Tp>;
618 }
619 };
620 template <class _Up>
621 using _CheckOptionalArgsCtor = conditional_t<
Marshall Clowd5bbc242018-02-06 20:56:55 +0000622 !is_same_v<__uncvref_t<_Up>, in_place_t> &&
623 !is_same_v<__uncvref_t<_Up>, optional>,
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000624 _CheckOptionalArgsConstructor,
625 __check_tuple_constructor_fail
626 >;
627 template <class _QualUp>
628 struct _CheckOptionalLikeConstructor {
629 template <class _Up, class _Opt = optional<_Up>>
630 using __check_constructible_from_opt = __lazy_or<
631 is_constructible<_Tp, _Opt&>,
632 is_constructible<_Tp, _Opt const&>,
633 is_constructible<_Tp, _Opt&&>,
634 is_constructible<_Tp, _Opt const&&>,
635 is_convertible<_Opt&, _Tp>,
636 is_convertible<_Opt const&, _Tp>,
637 is_convertible<_Opt&&, _Tp>,
638 is_convertible<_Opt const&&, _Tp>
639 >;
640 template <class _Up, class _Opt = optional<_Up>>
641 using __check_assignable_from_opt = __lazy_or<
642 is_assignable<_Tp&, _Opt&>,
643 is_assignable<_Tp&, _Opt const&>,
644 is_assignable<_Tp&, _Opt&&>,
645 is_assignable<_Tp&, _Opt const&&>
646 >;
647 template <class _Up, class _QUp = _QualUp>
648 static constexpr bool __enable_implicit() {
649 return is_convertible<_QUp, _Tp>::value &&
650 !__check_constructible_from_opt<_Up>::value;
651 }
652 template <class _Up, class _QUp = _QualUp>
653 static constexpr bool __enable_explicit() {
654 return !is_convertible<_QUp, _Tp>::value &&
655 !__check_constructible_from_opt<_Up>::value;
656 }
657 template <class _Up, class _QUp = _QualUp>
658 static constexpr bool __enable_assign() {
659 // Construction and assignability of _Qup to _Tp has already been
660 // checked.
661 return !__check_constructible_from_opt<_Up>::value &&
662 !__check_assignable_from_opt<_Up>::value;
663 }
664 };
665
666 template <class _Up, class _QualUp>
667 using _CheckOptionalLikeCtor = conditional_t<
668 __lazy_and<
669 __lazy_not<is_same<_Up, _Tp>>,
670 is_constructible<_Tp, _QualUp>
671 >::value,
672 _CheckOptionalLikeConstructor<_QualUp>,
673 __check_tuple_constructor_fail
674 >;
675 template <class _Up, class _QualUp>
676 using _CheckOptionalLikeAssign = conditional_t<
677 __lazy_and<
678 __lazy_not<is_same<_Up, _Tp>>,
679 is_constructible<_Tp, _QualUp>,
680 is_assignable<_Tp&, _QualUp>
681 >::value,
682 _CheckOptionalLikeConstructor<_QualUp>,
683 __check_tuple_constructor_fail
684 >;
685public:
686
687 _LIBCPP_INLINE_VISIBILITY constexpr optional() noexcept {}
Marshall Clowd44e2e32017-05-17 15:30:01 +0000688 _LIBCPP_INLINE_VISIBILITY constexpr optional(const optional&) = default;
689 _LIBCPP_INLINE_VISIBILITY constexpr optional(optional&&) = default;
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000690 _LIBCPP_INLINE_VISIBILITY constexpr optional(nullopt_t) noexcept {}
691
Eric Fiselier82103932019-03-11 22:55:21 +0000692 template <class _InPlaceT, class... _Args, class = enable_if_t<
693 __lazy_and<
694 is_same<_InPlaceT, in_place_t>,
695 is_constructible<value_type, _Args...>
696 >::value
697 >
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000698 >
699 _LIBCPP_INLINE_VISIBILITY
Eric Fiselier82103932019-03-11 22:55:21 +0000700 constexpr explicit optional(_InPlaceT, _Args&&... __args)
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000701 : __base(in_place, _VSTD::forward<_Args>(__args)...) {}
702
703 template <class _Up, class... _Args, class = enable_if_t<
704 is_constructible_v<value_type, initializer_list<_Up>&, _Args...>>
705 >
706 _LIBCPP_INLINE_VISIBILITY
707 constexpr explicit optional(in_place_t, initializer_list<_Up> __il, _Args&&... __args)
708 : __base(in_place, __il, _VSTD::forward<_Args>(__args)...) {}
709
710 template <class _Up = value_type, enable_if_t<
711 _CheckOptionalArgsCtor<_Up>::template __enable_implicit<_Up>()
712 , int> = 0>
713 _LIBCPP_INLINE_VISIBILITY
714 constexpr optional(_Up&& __v)
715 : __base(in_place, _VSTD::forward<_Up>(__v)) {}
716
717 template <class _Up, enable_if_t<
718 _CheckOptionalArgsCtor<_Up>::template __enable_explicit<_Up>()
719 , int> = 0>
720 _LIBCPP_INLINE_VISIBILITY
721 constexpr explicit optional(_Up&& __v)
722 : __base(in_place, _VSTD::forward<_Up>(__v)) {}
723
724 // LWG2756: conditionally explicit conversion from const optional<_Up>&
725 template <class _Up, enable_if_t<
726 _CheckOptionalLikeCtor<_Up, _Up const&>::template __enable_implicit<_Up>()
727 , int> = 0>
728 _LIBCPP_INLINE_VISIBILITY
729 optional(const optional<_Up>& __v)
730 {
731 this->__construct_from(__v);
732 }
733 template <class _Up, enable_if_t<
734 _CheckOptionalLikeCtor<_Up, _Up const&>::template __enable_explicit<_Up>()
735 , int> = 0>
736 _LIBCPP_INLINE_VISIBILITY
737 explicit optional(const optional<_Up>& __v)
738 {
739 this->__construct_from(__v);
740 }
741
742 // LWG2756: conditionally explicit conversion from optional<_Up>&&
743 template <class _Up, enable_if_t<
744 _CheckOptionalLikeCtor<_Up, _Up &&>::template __enable_implicit<_Up>()
745 , int> = 0>
746 _LIBCPP_INLINE_VISIBILITY
747 optional(optional<_Up>&& __v)
748 {
749 this->__construct_from(_VSTD::move(__v));
750 }
751 template <class _Up, enable_if_t<
752 _CheckOptionalLikeCtor<_Up, _Up &&>::template __enable_explicit<_Up>()
753 , int> = 0>
754 _LIBCPP_INLINE_VISIBILITY
755 explicit optional(optional<_Up>&& __v)
756 {
757 this->__construct_from(_VSTD::move(__v));
758 }
759
760 _LIBCPP_INLINE_VISIBILITY
761 optional& operator=(nullopt_t) noexcept
762 {
763 reset();
764 return *this;
765 }
766
767 _LIBCPP_INLINE_VISIBILITY optional& operator=(const optional&) = default;
768 _LIBCPP_INLINE_VISIBILITY optional& operator=(optional&&) = default;
769
770 // LWG2756
771 template <class _Up = value_type,
772 class = enable_if_t
Eric Fiselierb9014262016-10-16 03:21:35 +0000773 <__lazy_and<
774 integral_constant<bool,
Marshall Clowd5bbc242018-02-06 20:56:55 +0000775 !is_same_v<__uncvref_t<_Up>, optional> &&
Eric Fiselierb9014262016-10-16 03:21:35 +0000776 !(is_same_v<_Up, value_type> && is_scalar_v<value_type>)
777 >,
778 is_constructible<value_type, _Up>,
779 is_assignable<value_type&, _Up>
780 >::value>
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000781 >
782 _LIBCPP_INLINE_VISIBILITY
783 optional&
784 operator=(_Up&& __v)
785 {
786 if (this->has_value())
787 this->__get() = _VSTD::forward<_Up>(__v);
788 else
789 this->__construct(_VSTD::forward<_Up>(__v));
790 return *this;
791 }
792
793 // LWG2756
794 template <class _Up, enable_if_t<
795 _CheckOptionalLikeAssign<_Up, _Up const&>::template __enable_assign<_Up>()
796 , int> = 0>
797 _LIBCPP_INLINE_VISIBILITY
798 optional&
799 operator=(const optional<_Up>& __v)
800 {
801 this->__assign_from(__v);
802 return *this;
803 }
804
805 // LWG2756
806 template <class _Up, enable_if_t<
807 _CheckOptionalLikeCtor<_Up, _Up &&>::template __enable_assign<_Up>()
808 , int> = 0>
809 _LIBCPP_INLINE_VISIBILITY
810 optional&
811 operator=(optional<_Up>&& __v)
812 {
813 this->__assign_from(_VSTD::move(__v));
814 return *this;
815 }
816
817 template <class... _Args,
818 class = enable_if_t
819 <
820 is_constructible_v<value_type, _Args...>
821 >
822 >
823 _LIBCPP_INLINE_VISIBILITY
Marshall Clow45ff9822017-04-12 22:51:27 +0000824 _Tp &
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000825 emplace(_Args&&... __args)
826 {
827 reset();
828 this->__construct(_VSTD::forward<_Args>(__args)...);
Marshall Clow45ff9822017-04-12 22:51:27 +0000829 return this->__get();
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000830 }
831
832 template <class _Up, class... _Args,
833 class = enable_if_t
834 <
835 is_constructible_v<value_type, initializer_list<_Up>&, _Args...>
836 >
837 >
838 _LIBCPP_INLINE_VISIBILITY
Marshall Clow45ff9822017-04-12 22:51:27 +0000839 _Tp &
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000840 emplace(initializer_list<_Up> __il, _Args&&... __args)
841 {
842 reset();
843 this->__construct(__il, _VSTD::forward<_Args>(__args)...);
Marshall Clow45ff9822017-04-12 22:51:27 +0000844 return this->__get();
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000845 }
846
847 _LIBCPP_INLINE_VISIBILITY
848 void swap(optional& __opt)
849 noexcept(is_nothrow_move_constructible_v<value_type> &&
850 is_nothrow_swappable_v<value_type>)
851 {
852 if (this->has_value() == __opt.has_value())
853 {
854 using _VSTD::swap;
855 if (this->has_value())
856 swap(this->__get(), __opt.__get());
857 }
858 else
859 {
860 if (this->has_value())
861 {
862 __opt.__construct(_VSTD::move(this->__get()));
863 reset();
864 }
865 else
866 {
867 this->__construct(_VSTD::move(__opt.__get()));
868 __opt.reset();
869 }
870 }
871 }
872
873 _LIBCPP_INLINE_VISIBILITY
874 constexpr
875 add_pointer_t<value_type const>
876 operator->() const
877 {
878 _LIBCPP_ASSERT(this->has_value(), "optional operator-> called for disengaged value");
879#ifndef _LIBCPP_HAS_NO_BUILTIN_ADDRESSOF
880 return _VSTD::addressof(this->__get());
881#else
882 return __operator_arrow(__has_operator_addressof<value_type>{}, this->__get());
883#endif
884 }
885
886 _LIBCPP_INLINE_VISIBILITY
887 constexpr
888 add_pointer_t<value_type>
889 operator->()
890 {
891 _LIBCPP_ASSERT(this->has_value(), "optional operator-> called for disengaged value");
892#ifndef _LIBCPP_HAS_NO_BUILTIN_ADDRESSOF
893 return _VSTD::addressof(this->__get());
894#else
895 return __operator_arrow(__has_operator_addressof<value_type>{}, this->__get());
896#endif
897 }
898
899 _LIBCPP_INLINE_VISIBILITY
900 constexpr
901 const value_type&
902 operator*() const&
903 {
904 _LIBCPP_ASSERT(this->has_value(), "optional operator* called for disengaged value");
905 return this->__get();
906 }
907
908 _LIBCPP_INLINE_VISIBILITY
909 constexpr
910 value_type&
911 operator*() &
912 {
913 _LIBCPP_ASSERT(this->has_value(), "optional operator* called for disengaged value");
914 return this->__get();
915 }
916
917 _LIBCPP_INLINE_VISIBILITY
918 constexpr
919 value_type&&
920 operator*() &&
921 {
922 _LIBCPP_ASSERT(this->has_value(), "optional operator* called for disengaged value");
923 return _VSTD::move(this->__get());
924 }
925
926 _LIBCPP_INLINE_VISIBILITY
927 constexpr
928 const value_type&&
929 operator*() const&&
930 {
931 _LIBCPP_ASSERT(this->has_value(), "optional operator* called for disengaged value");
932 return _VSTD::move(this->__get());
933 }
934
935 _LIBCPP_INLINE_VISIBILITY
936 constexpr explicit operator bool() const noexcept { return has_value(); }
937
938 using __base::has_value;
939 using __base::__get;
940
941 _LIBCPP_INLINE_VISIBILITY
Louis Dionnecef92e62018-11-19 15:37:04 +0000942 _LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000943 constexpr value_type const& value() const&
944 {
945 if (!this->has_value())
946 __throw_bad_optional_access();
947 return this->__get();
948 }
949
950 _LIBCPP_INLINE_VISIBILITY
Louis Dionnecef92e62018-11-19 15:37:04 +0000951 _LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000952 constexpr value_type& value() &
953 {
954 if (!this->has_value())
955 __throw_bad_optional_access();
956 return this->__get();
957 }
958
959 _LIBCPP_INLINE_VISIBILITY
Louis Dionnecef92e62018-11-19 15:37:04 +0000960 _LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000961 constexpr value_type&& value() &&
962 {
963 if (!this->has_value())
964 __throw_bad_optional_access();
965 return _VSTD::move(this->__get());
966 }
967
968 _LIBCPP_INLINE_VISIBILITY
Louis Dionnecef92e62018-11-19 15:37:04 +0000969 _LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000970 constexpr value_type const&& value() const&&
971 {
972 if (!this->has_value())
973 __throw_bad_optional_access();
974 return _VSTD::move(this->__get());
975 }
976
977 template <class _Up>
978 _LIBCPP_INLINE_VISIBILITY
979 constexpr value_type value_or(_Up&& __v) const&
980 {
981 static_assert(is_copy_constructible_v<value_type>,
982 "optional<T>::value_or: T must be copy constructible");
983 static_assert(is_convertible_v<_Up, value_type>,
984 "optional<T>::value_or: U must be convertible to T");
985 return this->has_value() ? this->__get() :
986 static_cast<value_type>(_VSTD::forward<_Up>(__v));
987 }
988
989 template <class _Up>
990 _LIBCPP_INLINE_VISIBILITY
Casey Cartercb05fae2017-06-06 18:47:26 +0000991 constexpr value_type value_or(_Up&& __v) &&
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000992 {
993 static_assert(is_move_constructible_v<value_type>,
994 "optional<T>::value_or: T must be move constructible");
995 static_assert(is_convertible_v<_Up, value_type>,
996 "optional<T>::value_or: U must be convertible to T");
997 return this->has_value() ? _VSTD::move(this->__get()) :
998 static_cast<value_type>(_VSTD::forward<_Up>(__v));
999 }
1000
1001 using __base::reset;
1002
1003private:
1004 template <class _Up>
1005 _LIBCPP_INLINE_VISIBILITY
1006 static _Up*
1007 __operator_arrow(true_type, _Up& __x)
1008 {
1009 return _VSTD::addressof(__x);
1010 }
1011
1012 template <class _Up>
1013 _LIBCPP_INLINE_VISIBILITY
1014 static constexpr _Up*
1015 __operator_arrow(false_type, _Up& __x)
1016 {
1017 return &__x;
1018 }
1019};
1020
Marshall Clowe3c71ae2018-05-25 02:08:49 +00001021#ifndef _LIBCPP_HAS_NO_DEDUCTION_GUIDES
1022template<class T>
1023 optional(T) -> optional<T>;
1024#endif
1025
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001026// Comparisons between optionals
Eric Fiselier8af90142017-03-30 20:06:52 +00001027template <class _Tp, class _Up>
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001028_LIBCPP_INLINE_VISIBILITY constexpr
1029enable_if_t<
1030 is_convertible_v<decltype(_VSTD::declval<const _Tp&>() ==
Eric Fiselier8af90142017-03-30 20:06:52 +00001031 _VSTD::declval<const _Up&>()), bool>,
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001032 bool
1033>
Eric Fiselier8af90142017-03-30 20:06:52 +00001034operator==(const optional<_Tp>& __x, const optional<_Up>& __y)
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001035{
1036 if (static_cast<bool>(__x) != static_cast<bool>(__y))
1037 return false;
1038 if (!static_cast<bool>(__x))
1039 return true;
1040 return *__x == *__y;
1041}
1042
Eric Fiselier8af90142017-03-30 20:06:52 +00001043template <class _Tp, class _Up>
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001044_LIBCPP_INLINE_VISIBILITY constexpr
1045enable_if_t<
1046 is_convertible_v<decltype(_VSTD::declval<const _Tp&>() !=
Eric Fiselier8af90142017-03-30 20:06:52 +00001047 _VSTD::declval<const _Up&>()), bool>,
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001048 bool
1049>
Eric Fiselier8af90142017-03-30 20:06:52 +00001050operator!=(const optional<_Tp>& __x, const optional<_Up>& __y)
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001051{
1052 if (static_cast<bool>(__x) != static_cast<bool>(__y))
1053 return true;
1054 if (!static_cast<bool>(__x))
1055 return false;
1056 return *__x != *__y;
1057}
1058
Eric Fiselier8af90142017-03-30 20:06:52 +00001059template <class _Tp, class _Up>
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001060_LIBCPP_INLINE_VISIBILITY constexpr
1061enable_if_t<
1062 is_convertible_v<decltype(_VSTD::declval<const _Tp&>() <
Eric Fiselier8af90142017-03-30 20:06:52 +00001063 _VSTD::declval<const _Up&>()), bool>,
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001064 bool
1065>
Eric Fiselier8af90142017-03-30 20:06:52 +00001066operator<(const optional<_Tp>& __x, const optional<_Up>& __y)
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001067{
1068 if (!static_cast<bool>(__y))
1069 return false;
1070 if (!static_cast<bool>(__x))
1071 return true;
1072 return *__x < *__y;
1073}
1074
Eric Fiselier8af90142017-03-30 20:06:52 +00001075template <class _Tp, class _Up>
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001076_LIBCPP_INLINE_VISIBILITY constexpr
1077enable_if_t<
1078 is_convertible_v<decltype(_VSTD::declval<const _Tp&>() >
Eric Fiselier8af90142017-03-30 20:06:52 +00001079 _VSTD::declval<const _Up&>()), bool>,
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001080 bool
1081>
Eric Fiselier8af90142017-03-30 20:06:52 +00001082operator>(const optional<_Tp>& __x, const optional<_Up>& __y)
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001083{
1084 if (!static_cast<bool>(__x))
1085 return false;
1086 if (!static_cast<bool>(__y))
1087 return true;
1088 return *__x > *__y;
1089}
1090
Eric Fiselier8af90142017-03-30 20:06:52 +00001091template <class _Tp, class _Up>
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001092_LIBCPP_INLINE_VISIBILITY constexpr
1093enable_if_t<
1094 is_convertible_v<decltype(_VSTD::declval<const _Tp&>() <=
Eric Fiselier8af90142017-03-30 20:06:52 +00001095 _VSTD::declval<const _Up&>()), bool>,
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001096 bool
1097>
Eric Fiselier8af90142017-03-30 20:06:52 +00001098operator<=(const optional<_Tp>& __x, const optional<_Up>& __y)
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001099{
1100 if (!static_cast<bool>(__x))
1101 return true;
1102 if (!static_cast<bool>(__y))
1103 return false;
1104 return *__x <= *__y;
1105}
1106
Eric Fiselier8af90142017-03-30 20:06:52 +00001107template <class _Tp, class _Up>
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001108_LIBCPP_INLINE_VISIBILITY constexpr
1109enable_if_t<
1110 is_convertible_v<decltype(_VSTD::declval<const _Tp&>() >=
Eric Fiselier8af90142017-03-30 20:06:52 +00001111 _VSTD::declval<const _Up&>()), bool>,
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001112 bool
1113>
Eric Fiselier8af90142017-03-30 20:06:52 +00001114operator>=(const optional<_Tp>& __x, const optional<_Up>& __y)
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001115{
1116 if (!static_cast<bool>(__y))
1117 return true;
1118 if (!static_cast<bool>(__x))
1119 return false;
1120 return *__x >= *__y;
1121}
1122
1123// Comparisons with nullopt
1124template <class _Tp>
1125_LIBCPP_INLINE_VISIBILITY constexpr
1126bool
1127operator==(const optional<_Tp>& __x, nullopt_t) noexcept
1128{
1129 return !static_cast<bool>(__x);
1130}
1131
1132template <class _Tp>
1133_LIBCPP_INLINE_VISIBILITY constexpr
1134bool
1135operator==(nullopt_t, const optional<_Tp>& __x) noexcept
1136{
1137 return !static_cast<bool>(__x);
1138}
1139
1140template <class _Tp>
1141_LIBCPP_INLINE_VISIBILITY constexpr
1142bool
1143operator!=(const optional<_Tp>& __x, nullopt_t) noexcept
1144{
1145 return static_cast<bool>(__x);
1146}
1147
1148template <class _Tp>
1149_LIBCPP_INLINE_VISIBILITY constexpr
1150bool
1151operator!=(nullopt_t, const optional<_Tp>& __x) noexcept
1152{
1153 return static_cast<bool>(__x);
1154}
1155
1156template <class _Tp>
1157_LIBCPP_INLINE_VISIBILITY constexpr
1158bool
1159operator<(const optional<_Tp>&, nullopt_t) noexcept
1160{
1161 return false;
1162}
1163
1164template <class _Tp>
1165_LIBCPP_INLINE_VISIBILITY constexpr
1166bool
1167operator<(nullopt_t, const optional<_Tp>& __x) noexcept
1168{
1169 return static_cast<bool>(__x);
1170}
1171
1172template <class _Tp>
1173_LIBCPP_INLINE_VISIBILITY constexpr
1174bool
1175operator<=(const optional<_Tp>& __x, nullopt_t) noexcept
1176{
1177 return !static_cast<bool>(__x);
1178}
1179
1180template <class _Tp>
1181_LIBCPP_INLINE_VISIBILITY constexpr
1182bool
Eric Fiselier6003c772016-12-23 23:37:52 +00001183operator<=(nullopt_t, const optional<_Tp>&) noexcept
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001184{
1185 return true;
1186}
1187
1188template <class _Tp>
1189_LIBCPP_INLINE_VISIBILITY constexpr
1190bool
1191operator>(const optional<_Tp>& __x, nullopt_t) noexcept
1192{
1193 return static_cast<bool>(__x);
1194}
1195
1196template <class _Tp>
1197_LIBCPP_INLINE_VISIBILITY constexpr
1198bool
Eric Fiselier6003c772016-12-23 23:37:52 +00001199operator>(nullopt_t, const optional<_Tp>&) noexcept
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001200{
1201 return false;
1202}
1203
1204template <class _Tp>
1205_LIBCPP_INLINE_VISIBILITY constexpr
1206bool
1207operator>=(const optional<_Tp>&, nullopt_t) noexcept
1208{
1209 return true;
1210}
1211
1212template <class _Tp>
1213_LIBCPP_INLINE_VISIBILITY constexpr
1214bool
1215operator>=(nullopt_t, const optional<_Tp>& __x) noexcept
1216{
1217 return !static_cast<bool>(__x);
1218}
1219
1220// Comparisons with T
Eric Fiselier8af90142017-03-30 20:06:52 +00001221template <class _Tp, class _Up>
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001222_LIBCPP_INLINE_VISIBILITY constexpr
1223enable_if_t<
1224 is_convertible_v<decltype(_VSTD::declval<const _Tp&>() ==
Eric Fiselier8af90142017-03-30 20:06:52 +00001225 _VSTD::declval<const _Up&>()), bool>,
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001226 bool
1227>
Eric Fiselier8af90142017-03-30 20:06:52 +00001228operator==(const optional<_Tp>& __x, const _Up& __v)
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001229{
1230 return static_cast<bool>(__x) ? *__x == __v : false;
1231}
1232
Eric Fiselier8af90142017-03-30 20:06:52 +00001233template <class _Tp, class _Up>
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001234_LIBCPP_INLINE_VISIBILITY constexpr
1235enable_if_t<
1236 is_convertible_v<decltype(_VSTD::declval<const _Tp&>() ==
Eric Fiselier8af90142017-03-30 20:06:52 +00001237 _VSTD::declval<const _Up&>()), bool>,
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001238 bool
1239>
Eric Fiselier8af90142017-03-30 20:06:52 +00001240operator==(const _Tp& __v, const optional<_Up>& __x)
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001241{
1242 return static_cast<bool>(__x) ? __v == *__x : false;
1243}
1244
Eric Fiselier8af90142017-03-30 20:06:52 +00001245template <class _Tp, class _Up>
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001246_LIBCPP_INLINE_VISIBILITY constexpr
1247enable_if_t<
1248 is_convertible_v<decltype(_VSTD::declval<const _Tp&>() !=
Eric Fiselier8af90142017-03-30 20:06:52 +00001249 _VSTD::declval<const _Up&>()), bool>,
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001250 bool
1251>
Eric Fiselier8af90142017-03-30 20:06:52 +00001252operator!=(const optional<_Tp>& __x, const _Up& __v)
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001253{
1254 return static_cast<bool>(__x) ? *__x != __v : true;
1255}
1256
Eric Fiselier8af90142017-03-30 20:06:52 +00001257template <class _Tp, class _Up>
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001258_LIBCPP_INLINE_VISIBILITY constexpr
1259enable_if_t<
1260 is_convertible_v<decltype(_VSTD::declval<const _Tp&>() !=
Eric Fiselier8af90142017-03-30 20:06:52 +00001261 _VSTD::declval<const _Up&>()), bool>,
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001262 bool
1263>
Eric Fiselier8af90142017-03-30 20:06:52 +00001264operator!=(const _Tp& __v, const optional<_Up>& __x)
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001265{
1266 return static_cast<bool>(__x) ? __v != *__x : true;
1267}
1268
Eric Fiselier8af90142017-03-30 20:06:52 +00001269template <class _Tp, class _Up>
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001270_LIBCPP_INLINE_VISIBILITY constexpr
1271enable_if_t<
1272 is_convertible_v<decltype(_VSTD::declval<const _Tp&>() <
Eric Fiselier8af90142017-03-30 20:06:52 +00001273 _VSTD::declval<const _Up&>()), bool>,
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001274 bool
1275>
Eric Fiselier8af90142017-03-30 20:06:52 +00001276operator<(const optional<_Tp>& __x, const _Up& __v)
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001277{
1278 return static_cast<bool>(__x) ? *__x < __v : true;
1279}
1280
Eric Fiselier8af90142017-03-30 20:06:52 +00001281template <class _Tp, class _Up>
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001282_LIBCPP_INLINE_VISIBILITY constexpr
1283enable_if_t<
1284 is_convertible_v<decltype(_VSTD::declval<const _Tp&>() <
Eric Fiselier8af90142017-03-30 20:06:52 +00001285 _VSTD::declval<const _Up&>()), bool>,
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001286 bool
1287>
Eric Fiselier8af90142017-03-30 20:06:52 +00001288operator<(const _Tp& __v, const optional<_Up>& __x)
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001289{
1290 return static_cast<bool>(__x) ? __v < *__x : false;
1291}
1292
Eric Fiselier8af90142017-03-30 20:06:52 +00001293template <class _Tp, class _Up>
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001294_LIBCPP_INLINE_VISIBILITY constexpr
1295enable_if_t<
1296 is_convertible_v<decltype(_VSTD::declval<const _Tp&>() <=
Eric Fiselier8af90142017-03-30 20:06:52 +00001297 _VSTD::declval<const _Up&>()), bool>,
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001298 bool
1299>
Eric Fiselier8af90142017-03-30 20:06:52 +00001300operator<=(const optional<_Tp>& __x, const _Up& __v)
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001301{
1302 return static_cast<bool>(__x) ? *__x <= __v : true;
1303}
1304
Eric Fiselier8af90142017-03-30 20:06:52 +00001305template <class _Tp, class _Up>
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001306_LIBCPP_INLINE_VISIBILITY constexpr
1307enable_if_t<
1308 is_convertible_v<decltype(_VSTD::declval<const _Tp&>() <=
Eric Fiselier8af90142017-03-30 20:06:52 +00001309 _VSTD::declval<const _Up&>()), bool>,
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001310 bool
1311>
Eric Fiselier8af90142017-03-30 20:06:52 +00001312operator<=(const _Tp& __v, const optional<_Up>& __x)
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001313{
1314 return static_cast<bool>(__x) ? __v <= *__x : false;
1315}
1316
Eric Fiselier8af90142017-03-30 20:06:52 +00001317template <class _Tp, class _Up>
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001318_LIBCPP_INLINE_VISIBILITY constexpr
1319enable_if_t<
1320 is_convertible_v<decltype(_VSTD::declval<const _Tp&>() >
Eric Fiselier8af90142017-03-30 20:06:52 +00001321 _VSTD::declval<const _Up&>()), bool>,
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001322 bool
1323>
Eric Fiselier8af90142017-03-30 20:06:52 +00001324operator>(const optional<_Tp>& __x, const _Up& __v)
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001325{
1326 return static_cast<bool>(__x) ? *__x > __v : false;
1327}
1328
Eric Fiselier8af90142017-03-30 20:06:52 +00001329template <class _Tp, class _Up>
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001330_LIBCPP_INLINE_VISIBILITY constexpr
1331enable_if_t<
1332 is_convertible_v<decltype(_VSTD::declval<const _Tp&>() >
Eric Fiselier8af90142017-03-30 20:06:52 +00001333 _VSTD::declval<const _Up&>()), bool>,
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001334 bool
1335>
Eric Fiselier8af90142017-03-30 20:06:52 +00001336operator>(const _Tp& __v, const optional<_Up>& __x)
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001337{
1338 return static_cast<bool>(__x) ? __v > *__x : true;
1339}
1340
Eric Fiselier8af90142017-03-30 20:06:52 +00001341template <class _Tp, class _Up>
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001342_LIBCPP_INLINE_VISIBILITY constexpr
1343enable_if_t<
1344 is_convertible_v<decltype(_VSTD::declval<const _Tp&>() >=
Eric Fiselier8af90142017-03-30 20:06:52 +00001345 _VSTD::declval<const _Up&>()), bool>,
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001346 bool
1347>
Eric Fiselier8af90142017-03-30 20:06:52 +00001348operator>=(const optional<_Tp>& __x, const _Up& __v)
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001349{
1350 return static_cast<bool>(__x) ? *__x >= __v : false;
1351}
1352
Eric Fiselier8af90142017-03-30 20:06:52 +00001353template <class _Tp, class _Up>
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001354_LIBCPP_INLINE_VISIBILITY constexpr
1355enable_if_t<
1356 is_convertible_v<decltype(_VSTD::declval<const _Tp&>() >=
Eric Fiselier8af90142017-03-30 20:06:52 +00001357 _VSTD::declval<const _Up&>()), bool>,
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001358 bool
1359>
Eric Fiselier8af90142017-03-30 20:06:52 +00001360operator>=(const _Tp& __v, const optional<_Up>& __x)
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001361{
1362 return static_cast<bool>(__x) ? __v >= *__x : true;
1363}
1364
1365
1366template <class _Tp>
1367inline _LIBCPP_INLINE_VISIBILITY
1368enable_if_t<
1369 is_move_constructible_v<_Tp> && is_swappable_v<_Tp>,
1370 void
1371>
1372swap(optional<_Tp>& __x, optional<_Tp>& __y) noexcept(noexcept(__x.swap(__y)))
1373{
1374 __x.swap(__y);
1375}
1376
1377template <class _Tp>
1378_LIBCPP_INLINE_VISIBILITY constexpr
1379optional<decay_t<_Tp>> make_optional(_Tp&& __v)
1380{
1381 return optional<decay_t<_Tp>>(_VSTD::forward<_Tp>(__v));
1382}
1383
1384template <class _Tp, class... _Args>
1385_LIBCPP_INLINE_VISIBILITY constexpr
1386optional<_Tp> make_optional(_Args&&... __args)
1387{
1388 return optional<_Tp>(in_place, _VSTD::forward<_Args>(__args)...);
1389}
1390
1391template <class _Tp, class _Up, class... _Args>
1392_LIBCPP_INLINE_VISIBILITY constexpr
1393optional<_Tp> make_optional(initializer_list<_Up> __il, _Args&&... __args)
1394{
1395 return optional<_Tp>(in_place, __il, _VSTD::forward<_Args>(__args)...);
1396}
1397
1398template <class _Tp>
Eric Fiselier698a97b2017-01-21 00:02:12 +00001399struct _LIBCPP_TEMPLATE_VIS hash<
1400 __enable_hash_helper<optional<_Tp>, remove_const_t<_Tp>>
1401>
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001402{
1403 typedef optional<_Tp> argument_type;
1404 typedef size_t result_type;
1405
1406 _LIBCPP_INLINE_VISIBILITY
Marshall Clow49036892017-03-23 02:40:28 +00001407 result_type operator()(const argument_type& __opt) const
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001408 {
Eric Fiselier698a97b2017-01-21 00:02:12 +00001409 return static_cast<bool>(__opt) ? hash<remove_const_t<_Tp>>()(*__opt) : 0;
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001410 }
1411};
1412
1413_LIBCPP_END_NAMESPACE_STD
1414
1415#endif // _LIBCPP_STD_VER > 14
1416
Eric Fiselierf4433a32017-05-31 22:07:49 +00001417_LIBCPP_POP_MACROS
1418
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001419#endif // _LIBCPP_OPTIONAL