blob: 97a0bbe66ca973c87bb1bb3c56b65afaa3c141c7 [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>
Louis Dionne73912b22020-11-04 15:01:25 -0500150#include <__availability>
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000151#include <__debug>
152#include <__functional_base>
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000153#include <functional>
154#include <initializer_list>
155#include <new>
156#include <stdexcept>
157#include <type_traits>
158#include <utility>
Marshall Clow0a1e7502018-09-12 19:41:40 +0000159#include <version>
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000160
161#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
162#pragma GCC system_header
163#endif
164
Eric Fiselierf4433a32017-05-31 22:07:49 +0000165_LIBCPP_PUSH_MACROS
166#include <__undef_macros>
167
168
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000169namespace std // purposefully not using versioning namespace
170{
171
Louis Dionnecef92e62018-11-19 15:37:04 +0000172class _LIBCPP_EXCEPTION_ABI _LIBCPP_AVAILABILITY_BAD_OPTIONAL_ACCESS bad_optional_access
Marshall Clowa627d4a2017-02-05 20:06:38 +0000173 : public exception
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000174{
175public:
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000176 // Get the key function ~bad_optional_access() into the dylib
Marshall Clow53fc0372017-02-05 20:52:32 +0000177 virtual ~bad_optional_access() _NOEXCEPT;
Marshall Clowa627d4a2017-02-05 20:06:38 +0000178 virtual const char* what() const _NOEXCEPT;
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000179};
180
181} // std
182
183#if _LIBCPP_STD_VER > 14
184
185_LIBCPP_BEGIN_NAMESPACE_STD
186
187_LIBCPP_NORETURN
188inline _LIBCPP_INLINE_VISIBILITY
Louis Dionnecef92e62018-11-19 15:37:04 +0000189_LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000190void __throw_bad_optional_access() {
191#ifndef _LIBCPP_NO_EXCEPTIONS
192 throw bad_optional_access();
193#else
194 _VSTD::abort();
195#endif
196}
197
198struct nullopt_t
199{
200 struct __secret_tag { _LIBCPP_INLINE_VISIBILITY explicit __secret_tag() = default; };
201 _LIBCPP_INLINE_VISIBILITY constexpr explicit nullopt_t(__secret_tag, __secret_tag) noexcept {}
202};
203
Marshall Clowf1bf62f2018-01-02 17:17:01 +0000204_LIBCPP_INLINE_VAR constexpr nullopt_t nullopt{nullopt_t::__secret_tag{}, nullopt_t::__secret_tag{}};
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000205
206template <class _Tp, bool = is_trivially_destructible<_Tp>::value>
207struct __optional_destruct_base;
208
209template <class _Tp>
210struct __optional_destruct_base<_Tp, false>
211{
212 typedef _Tp value_type;
213 static_assert(is_object_v<value_type>,
214 "instantiation of optional with a non-object type is undefined behavior");
215 union
216 {
217 char __null_state_;
218 value_type __val_;
219 };
220 bool __engaged_;
221
222 _LIBCPP_INLINE_VISIBILITY
223 ~__optional_destruct_base()
224 {
225 if (__engaged_)
226 __val_.~value_type();
227 }
228
229 _LIBCPP_INLINE_VISIBILITY
230 constexpr __optional_destruct_base() noexcept
231 : __null_state_(),
232 __engaged_(false) {}
233
234 template <class... _Args>
235 _LIBCPP_INLINE_VISIBILITY
236 constexpr explicit __optional_destruct_base(in_place_t, _Args&&... __args)
237 : __val_(_VSTD::forward<_Args>(__args)...),
238 __engaged_(true) {}
239
240 _LIBCPP_INLINE_VISIBILITY
241 void reset() noexcept
242 {
243 if (__engaged_)
244 {
245 __val_.~value_type();
246 __engaged_ = false;
247 }
248 }
249};
250
251template <class _Tp>
252struct __optional_destruct_base<_Tp, true>
253{
254 typedef _Tp value_type;
255 static_assert(is_object_v<value_type>,
256 "instantiation of optional with a non-object type is undefined behavior");
257 union
258 {
259 char __null_state_;
260 value_type __val_;
261 };
262 bool __engaged_;
263
264 _LIBCPP_INLINE_VISIBILITY
265 constexpr __optional_destruct_base() noexcept
266 : __null_state_(),
267 __engaged_(false) {}
268
269 template <class... _Args>
270 _LIBCPP_INLINE_VISIBILITY
271 constexpr explicit __optional_destruct_base(in_place_t, _Args&&... __args)
272 : __val_(_VSTD::forward<_Args>(__args)...),
273 __engaged_(true) {}
274
275 _LIBCPP_INLINE_VISIBILITY
276 void reset() noexcept
277 {
278 if (__engaged_)
279 {
280 __engaged_ = false;
281 }
282 }
283};
284
285template <class _Tp, bool = is_reference<_Tp>::value>
286struct __optional_storage_base : __optional_destruct_base<_Tp>
287{
288 using __base = __optional_destruct_base<_Tp>;
289 using value_type = _Tp;
290 using __base::__base;
291
292 _LIBCPP_INLINE_VISIBILITY
293 constexpr bool has_value() const noexcept
294 {
295 return this->__engaged_;
296 }
297
298 _LIBCPP_INLINE_VISIBILITY
299 constexpr value_type& __get() & noexcept
300 {
301 return this->__val_;
302 }
303 _LIBCPP_INLINE_VISIBILITY
304 constexpr const value_type& __get() const& noexcept
305 {
306 return this->__val_;
307 }
308 _LIBCPP_INLINE_VISIBILITY
309 constexpr value_type&& __get() && noexcept
310 {
311 return _VSTD::move(this->__val_);
312 }
313 _LIBCPP_INLINE_VISIBILITY
314 constexpr const value_type&& __get() const&& noexcept
315 {
316 return _VSTD::move(this->__val_);
317 }
318
319 template <class... _Args>
320 _LIBCPP_INLINE_VISIBILITY
321 void __construct(_Args&&... __args)
322 {
323 _LIBCPP_ASSERT(!has_value(), "__construct called for engaged __optional_storage");
Arthur O'Dwyer0c4472a2020-12-11 20:30:28 -0500324 ::new ((void*)_VSTD::addressof(this->__val_)) value_type(_VSTD::forward<_Args>(__args)...);
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000325 this->__engaged_ = true;
326 }
327
328 template <class _That>
329 _LIBCPP_INLINE_VISIBILITY
330 void __construct_from(_That&& __opt)
331 {
332 if (__opt.has_value())
333 __construct(_VSTD::forward<_That>(__opt).__get());
334 }
335
336 template <class _That>
337 _LIBCPP_INLINE_VISIBILITY
338 void __assign_from(_That&& __opt)
339 {
340 if (this->__engaged_ == __opt.has_value())
341 {
342 if (this->__engaged_)
343 this->__val_ = _VSTD::forward<_That>(__opt).__get();
344 }
345 else
346 {
347 if (this->__engaged_)
348 this->reset();
349 else
350 __construct(_VSTD::forward<_That>(__opt).__get());
351 }
352 }
353};
354
355// optional<T&> is currently required ill-formed, however it may to be in the
356// future. For this reason it has already been implemented to ensure we can
357// make the change in an ABI compatible manner.
358template <class _Tp>
359struct __optional_storage_base<_Tp, true>
360{
361 using value_type = _Tp;
362 using __raw_type = remove_reference_t<_Tp>;
363 __raw_type* __value_;
364
365 template <class _Up>
366 static constexpr bool __can_bind_reference() {
367 using _RawUp = typename remove_reference<_Up>::type;
368 using _UpPtr = _RawUp*;
369 using _RawTp = typename remove_reference<_Tp>::type;
370 using _TpPtr = _RawTp*;
371 using _CheckLValueArg = integral_constant<bool,
372 (is_lvalue_reference<_Up>::value && is_convertible<_UpPtr, _TpPtr>::value)
373 || is_same<_RawUp, reference_wrapper<_RawTp>>::value
374 || is_same<_RawUp, reference_wrapper<typename remove_const<_RawTp>::type>>::value
375 >;
376 return (is_lvalue_reference<_Tp>::value && _CheckLValueArg::value)
377 || (is_rvalue_reference<_Tp>::value && !is_lvalue_reference<_Up>::value &&
378 is_convertible<_UpPtr, _TpPtr>::value);
379 }
380
381 _LIBCPP_INLINE_VISIBILITY
382 constexpr __optional_storage_base() noexcept
383 : __value_(nullptr) {}
384
385 template <class _UArg>
386 _LIBCPP_INLINE_VISIBILITY
387 constexpr explicit __optional_storage_base(in_place_t, _UArg&& __uarg)
388 : __value_(_VSTD::addressof(__uarg))
389 {
390 static_assert(__can_bind_reference<_UArg>(),
391 "Attempted to construct a reference element in tuple from a "
392 "possible temporary");
393 }
394
395 _LIBCPP_INLINE_VISIBILITY
396 void reset() noexcept { __value_ = nullptr; }
397
398 _LIBCPP_INLINE_VISIBILITY
399 constexpr bool has_value() const noexcept
400 { return __value_ != nullptr; }
401
402 _LIBCPP_INLINE_VISIBILITY
403 constexpr value_type& __get() const& noexcept
404 { return *__value_; }
405
406 _LIBCPP_INLINE_VISIBILITY
407 constexpr value_type&& __get() const&& noexcept
408 { return _VSTD::forward<value_type>(*__value_); }
409
410 template <class _UArg>
411 _LIBCPP_INLINE_VISIBILITY
412 void __construct(_UArg&& __val)
413 {
414 _LIBCPP_ASSERT(!has_value(), "__construct called for engaged __optional_storage");
415 static_assert(__can_bind_reference<_UArg>(),
416 "Attempted to construct a reference element in tuple from a "
417 "possible temporary");
418 __value_ = _VSTD::addressof(__val);
419 }
420
421 template <class _That>
422 _LIBCPP_INLINE_VISIBILITY
423 void __construct_from(_That&& __opt)
424 {
425 if (__opt.has_value())
426 __construct(_VSTD::forward<_That>(__opt).__get());
427 }
428
429 template <class _That>
430 _LIBCPP_INLINE_VISIBILITY
431 void __assign_from(_That&& __opt)
432 {
433 if (has_value() == __opt.has_value())
434 {
435 if (has_value())
436 *__value_ = _VSTD::forward<_That>(__opt).__get();
437 }
438 else
439 {
440 if (has_value())
441 reset();
442 else
443 __construct(_VSTD::forward<_That>(__opt).__get());
444 }
445 }
446};
447
Casey Carterc189f7f2017-07-09 17:15:49 +0000448template <class _Tp, bool = is_trivially_copy_constructible<_Tp>::value>
449struct __optional_copy_base : __optional_storage_base<_Tp>
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000450{
451 using __optional_storage_base<_Tp>::__optional_storage_base;
452};
453
454template <class _Tp>
Casey Carterc189f7f2017-07-09 17:15:49 +0000455struct __optional_copy_base<_Tp, false> : __optional_storage_base<_Tp>
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000456{
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000457 using __optional_storage_base<_Tp>::__optional_storage_base;
458
459 _LIBCPP_INLINE_VISIBILITY
Casey Carterc189f7f2017-07-09 17:15:49 +0000460 __optional_copy_base() = default;
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000461
462 _LIBCPP_INLINE_VISIBILITY
Casey Carterc189f7f2017-07-09 17:15:49 +0000463 __optional_copy_base(const __optional_copy_base& __opt)
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000464 {
465 this->__construct_from(__opt);
466 }
467
468 _LIBCPP_INLINE_VISIBILITY
Casey Carterc189f7f2017-07-09 17:15:49 +0000469 __optional_copy_base(__optional_copy_base&&) = default;
470 _LIBCPP_INLINE_VISIBILITY
471 __optional_copy_base& operator=(const __optional_copy_base&) = default;
472 _LIBCPP_INLINE_VISIBILITY
473 __optional_copy_base& operator=(__optional_copy_base&&) = default;
474};
475
476template <class _Tp, bool = is_trivially_move_constructible<_Tp>::value>
477struct __optional_move_base : __optional_copy_base<_Tp>
478{
479 using __optional_copy_base<_Tp>::__optional_copy_base;
480};
481
482template <class _Tp>
483struct __optional_move_base<_Tp, false> : __optional_copy_base<_Tp>
484{
485 using value_type = _Tp;
486 using __optional_copy_base<_Tp>::__optional_copy_base;
487
488 _LIBCPP_INLINE_VISIBILITY
489 __optional_move_base() = default;
490 _LIBCPP_INLINE_VISIBILITY
491 __optional_move_base(const __optional_move_base&) = default;
492
493 _LIBCPP_INLINE_VISIBILITY
494 __optional_move_base(__optional_move_base&& __opt)
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000495 noexcept(is_nothrow_move_constructible_v<value_type>)
496 {
497 this->__construct_from(_VSTD::move(__opt));
498 }
499
500 _LIBCPP_INLINE_VISIBILITY
Casey Carterc189f7f2017-07-09 17:15:49 +0000501 __optional_move_base& operator=(const __optional_move_base&) = default;
502 _LIBCPP_INLINE_VISIBILITY
503 __optional_move_base& operator=(__optional_move_base&&) = default;
504};
505
506template <class _Tp, bool =
507 is_trivially_destructible<_Tp>::value &&
508 is_trivially_copy_constructible<_Tp>::value &&
509 is_trivially_copy_assignable<_Tp>::value>
510struct __optional_copy_assign_base : __optional_move_base<_Tp>
511{
512 using __optional_move_base<_Tp>::__optional_move_base;
513};
514
515template <class _Tp>
516struct __optional_copy_assign_base<_Tp, false> : __optional_move_base<_Tp>
517{
518 using __optional_move_base<_Tp>::__optional_move_base;
519
520 _LIBCPP_INLINE_VISIBILITY
521 __optional_copy_assign_base() = default;
522 _LIBCPP_INLINE_VISIBILITY
523 __optional_copy_assign_base(const __optional_copy_assign_base&) = default;
524 _LIBCPP_INLINE_VISIBILITY
525 __optional_copy_assign_base(__optional_copy_assign_base&&) = default;
526
527 _LIBCPP_INLINE_VISIBILITY
528 __optional_copy_assign_base& operator=(const __optional_copy_assign_base& __opt)
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000529 {
530 this->__assign_from(__opt);
531 return *this;
532 }
533
534 _LIBCPP_INLINE_VISIBILITY
Casey Carterc189f7f2017-07-09 17:15:49 +0000535 __optional_copy_assign_base& operator=(__optional_copy_assign_base&&) = default;
536};
537
538template <class _Tp, bool =
539 is_trivially_destructible<_Tp>::value &&
540 is_trivially_move_constructible<_Tp>::value &&
541 is_trivially_move_assignable<_Tp>::value>
542struct __optional_move_assign_base : __optional_copy_assign_base<_Tp>
543{
544 using __optional_copy_assign_base<_Tp>::__optional_copy_assign_base;
545};
546
547template <class _Tp>
548struct __optional_move_assign_base<_Tp, false> : __optional_copy_assign_base<_Tp>
549{
550 using value_type = _Tp;
551 using __optional_copy_assign_base<_Tp>::__optional_copy_assign_base;
552
553 _LIBCPP_INLINE_VISIBILITY
554 __optional_move_assign_base() = default;
555 _LIBCPP_INLINE_VISIBILITY
556 __optional_move_assign_base(const __optional_move_assign_base& __opt) = default;
557 _LIBCPP_INLINE_VISIBILITY
558 __optional_move_assign_base(__optional_move_assign_base&&) = default;
559 _LIBCPP_INLINE_VISIBILITY
560 __optional_move_assign_base& operator=(const __optional_move_assign_base&) = default;
561
562 _LIBCPP_INLINE_VISIBILITY
563 __optional_move_assign_base& operator=(__optional_move_assign_base&& __opt)
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000564 noexcept(is_nothrow_move_assignable_v<value_type> &&
565 is_nothrow_move_constructible_v<value_type>)
566 {
567 this->__assign_from(_VSTD::move(__opt));
568 return *this;
569 }
570};
571
572template <class _Tp>
573using __optional_sfinae_ctor_base_t = __sfinae_ctor_base<
574 is_copy_constructible<_Tp>::value,
575 is_move_constructible<_Tp>::value
576>;
577
578template <class _Tp>
579using __optional_sfinae_assign_base_t = __sfinae_assign_base<
580 (is_copy_constructible<_Tp>::value && is_copy_assignable<_Tp>::value),
581 (is_move_constructible<_Tp>::value && is_move_assignable<_Tp>::value)
582>;
583
584template <class _Tp>
585class optional
Casey Carterc189f7f2017-07-09 17:15:49 +0000586 : private __optional_move_assign_base<_Tp>
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000587 , private __optional_sfinae_ctor_base_t<_Tp>
588 , private __optional_sfinae_assign_base_t<_Tp>
589{
Casey Carterc189f7f2017-07-09 17:15:49 +0000590 using __base = __optional_move_assign_base<_Tp>;
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000591public:
592 using value_type = _Tp;
593
594private:
595 // Disable the reference extension using this static assert.
Marshall Clowfa6a3342019-03-25 16:35:59 +0000596 static_assert(!is_same_v<__uncvref_t<value_type>, in_place_t>,
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000597 "instantiation of optional with in_place_t is ill-formed");
598 static_assert(!is_same_v<__uncvref_t<value_type>, nullopt_t>,
599 "instantiation of optional with nullopt_t is ill-formed");
600 static_assert(!is_reference_v<value_type>,
601 "instantiation of optional with a reference type is ill-formed");
602 static_assert(is_destructible_v<value_type>,
603 "instantiation of optional with a non-destructible type is ill-formed");
Marshall Clowfa6a3342019-03-25 16:35:59 +0000604 static_assert(!is_array_v<value_type>,
605 "instantiation of optional with an array type is ill-formed");
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000606
607 // LWG2756: conditionally explicit conversion from _Up
608 struct _CheckOptionalArgsConstructor {
609 template <class _Up>
610 static constexpr bool __enable_implicit() {
611 return is_constructible_v<_Tp, _Up&&> &&
612 is_convertible_v<_Up&&, _Tp>;
613 }
614
615 template <class _Up>
616 static constexpr bool __enable_explicit() {
617 return is_constructible_v<_Tp, _Up&&> &&
618 !is_convertible_v<_Up&&, _Tp>;
619 }
620 };
621 template <class _Up>
Eric Fiselier3906a132019-06-23 20:28:29 +0000622 using _CheckOptionalArgsCtor = _If<
623 _IsNotSame<__uncvref_t<_Up>, in_place_t>::value &&
624 _IsNotSame<__uncvref_t<_Up>, optional>::value,
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000625 _CheckOptionalArgsConstructor,
626 __check_tuple_constructor_fail
627 >;
628 template <class _QualUp>
629 struct _CheckOptionalLikeConstructor {
630 template <class _Up, class _Opt = optional<_Up>>
Eric Fiselier3906a132019-06-23 20:28:29 +0000631 using __check_constructible_from_opt = _Or<
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000632 is_constructible<_Tp, _Opt&>,
633 is_constructible<_Tp, _Opt const&>,
634 is_constructible<_Tp, _Opt&&>,
635 is_constructible<_Tp, _Opt const&&>,
636 is_convertible<_Opt&, _Tp>,
637 is_convertible<_Opt const&, _Tp>,
638 is_convertible<_Opt&&, _Tp>,
639 is_convertible<_Opt const&&, _Tp>
640 >;
641 template <class _Up, class _Opt = optional<_Up>>
Eric Fiselier3906a132019-06-23 20:28:29 +0000642 using __check_assignable_from_opt = _Or<
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000643 is_assignable<_Tp&, _Opt&>,
644 is_assignable<_Tp&, _Opt const&>,
645 is_assignable<_Tp&, _Opt&&>,
646 is_assignable<_Tp&, _Opt const&&>
647 >;
648 template <class _Up, class _QUp = _QualUp>
649 static constexpr bool __enable_implicit() {
650 return is_convertible<_QUp, _Tp>::value &&
651 !__check_constructible_from_opt<_Up>::value;
652 }
653 template <class _Up, class _QUp = _QualUp>
654 static constexpr bool __enable_explicit() {
655 return !is_convertible<_QUp, _Tp>::value &&
656 !__check_constructible_from_opt<_Up>::value;
657 }
658 template <class _Up, class _QUp = _QualUp>
659 static constexpr bool __enable_assign() {
Arthur O'Dwyerdf5df562020-12-12 11:57:32 -0500660 // Construction and assignability of _QUp to _Tp has already been
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000661 // checked.
662 return !__check_constructible_from_opt<_Up>::value &&
663 !__check_assignable_from_opt<_Up>::value;
664 }
665 };
666
667 template <class _Up, class _QualUp>
Eric Fiselier3906a132019-06-23 20:28:29 +0000668 using _CheckOptionalLikeCtor = _If<
669 _And<
670 _IsNotSame<_Up, _Tp>,
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000671 is_constructible<_Tp, _QualUp>
672 >::value,
673 _CheckOptionalLikeConstructor<_QualUp>,
674 __check_tuple_constructor_fail
675 >;
676 template <class _Up, class _QualUp>
Eric Fiselier3906a132019-06-23 20:28:29 +0000677 using _CheckOptionalLikeAssign = _If<
678 _And<
679 _IsNotSame<_Up, _Tp>,
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000680 is_constructible<_Tp, _QualUp>,
681 is_assignable<_Tp&, _QualUp>
682 >::value,
683 _CheckOptionalLikeConstructor<_QualUp>,
684 __check_tuple_constructor_fail
685 >;
686public:
687
688 _LIBCPP_INLINE_VISIBILITY constexpr optional() noexcept {}
Marshall Clowd44e2e32017-05-17 15:30:01 +0000689 _LIBCPP_INLINE_VISIBILITY constexpr optional(const optional&) = default;
690 _LIBCPP_INLINE_VISIBILITY constexpr optional(optional&&) = default;
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000691 _LIBCPP_INLINE_VISIBILITY constexpr optional(nullopt_t) noexcept {}
692
Eric Fiselier3906a132019-06-23 20:28:29 +0000693 template <class _InPlaceT, class... _Args, class = _EnableIf<
694 _And<
695 _IsSame<_InPlaceT, in_place_t>,
696 is_constructible<value_type, _Args...>
Eric Fiselier82103932019-03-11 22:55:21 +0000697 >::value
698 >
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000699 >
700 _LIBCPP_INLINE_VISIBILITY
Eric Fiselier82103932019-03-11 22:55:21 +0000701 constexpr explicit optional(_InPlaceT, _Args&&... __args)
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000702 : __base(in_place, _VSTD::forward<_Args>(__args)...) {}
703
Eric Fiselier3906a132019-06-23 20:28:29 +0000704 template <class _Up, class... _Args, class = _EnableIf<
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000705 is_constructible_v<value_type, initializer_list<_Up>&, _Args...>>
706 >
707 _LIBCPP_INLINE_VISIBILITY
708 constexpr explicit optional(in_place_t, initializer_list<_Up> __il, _Args&&... __args)
709 : __base(in_place, __il, _VSTD::forward<_Args>(__args)...) {}
710
Eric Fiselier3906a132019-06-23 20:28:29 +0000711 template <class _Up = value_type, _EnableIf<
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000712 _CheckOptionalArgsCtor<_Up>::template __enable_implicit<_Up>()
713 , int> = 0>
714 _LIBCPP_INLINE_VISIBILITY
715 constexpr optional(_Up&& __v)
716 : __base(in_place, _VSTD::forward<_Up>(__v)) {}
717
Eric Fiselier3906a132019-06-23 20:28:29 +0000718 template <class _Up, _EnableIf<
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000719 _CheckOptionalArgsCtor<_Up>::template __enable_explicit<_Up>()
720 , int> = 0>
721 _LIBCPP_INLINE_VISIBILITY
722 constexpr explicit optional(_Up&& __v)
723 : __base(in_place, _VSTD::forward<_Up>(__v)) {}
724
725 // LWG2756: conditionally explicit conversion from const optional<_Up>&
Eric Fiselier3906a132019-06-23 20:28:29 +0000726 template <class _Up, _EnableIf<
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000727 _CheckOptionalLikeCtor<_Up, _Up const&>::template __enable_implicit<_Up>()
728 , int> = 0>
729 _LIBCPP_INLINE_VISIBILITY
730 optional(const optional<_Up>& __v)
731 {
732 this->__construct_from(__v);
733 }
Eric Fiselier3906a132019-06-23 20:28:29 +0000734 template <class _Up, _EnableIf<
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000735 _CheckOptionalLikeCtor<_Up, _Up const&>::template __enable_explicit<_Up>()
736 , int> = 0>
737 _LIBCPP_INLINE_VISIBILITY
738 explicit optional(const optional<_Up>& __v)
739 {
740 this->__construct_from(__v);
741 }
742
743 // LWG2756: conditionally explicit conversion from optional<_Up>&&
Eric Fiselier3906a132019-06-23 20:28:29 +0000744 template <class _Up, _EnableIf<
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000745 _CheckOptionalLikeCtor<_Up, _Up &&>::template __enable_implicit<_Up>()
746 , int> = 0>
747 _LIBCPP_INLINE_VISIBILITY
748 optional(optional<_Up>&& __v)
749 {
750 this->__construct_from(_VSTD::move(__v));
751 }
Eric Fiselier3906a132019-06-23 20:28:29 +0000752 template <class _Up, _EnableIf<
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000753 _CheckOptionalLikeCtor<_Up, _Up &&>::template __enable_explicit<_Up>()
754 , int> = 0>
755 _LIBCPP_INLINE_VISIBILITY
756 explicit optional(optional<_Up>&& __v)
757 {
758 this->__construct_from(_VSTD::move(__v));
759 }
760
761 _LIBCPP_INLINE_VISIBILITY
762 optional& operator=(nullopt_t) noexcept
763 {
764 reset();
765 return *this;
766 }
767
768 _LIBCPP_INLINE_VISIBILITY optional& operator=(const optional&) = default;
769 _LIBCPP_INLINE_VISIBILITY optional& operator=(optional&&) = default;
770
771 // LWG2756
772 template <class _Up = value_type,
Eric Fiselier3906a132019-06-23 20:28:29 +0000773 class = _EnableIf<
774 _And<
775 _IsNotSame<__uncvref_t<_Up>, optional>,
776 _Or<
Marshall Clow99315112019-06-27 18:40:55 +0000777 _IsNotSame<__uncvref_t<_Up>, value_type>,
Eric Fiselier3906a132019-06-23 20:28:29 +0000778 _Not<is_scalar<value_type>>
Eric Fiselierb9014262016-10-16 03:21:35 +0000779 >,
780 is_constructible<value_type, _Up>,
781 is_assignable<value_type&, _Up>
782 >::value>
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000783 >
784 _LIBCPP_INLINE_VISIBILITY
785 optional&
786 operator=(_Up&& __v)
787 {
788 if (this->has_value())
789 this->__get() = _VSTD::forward<_Up>(__v);
790 else
791 this->__construct(_VSTD::forward<_Up>(__v));
792 return *this;
793 }
794
795 // LWG2756
Eric Fiselier3906a132019-06-23 20:28:29 +0000796 template <class _Up, _EnableIf<
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000797 _CheckOptionalLikeAssign<_Up, _Up const&>::template __enable_assign<_Up>()
798 , int> = 0>
799 _LIBCPP_INLINE_VISIBILITY
800 optional&
801 operator=(const optional<_Up>& __v)
802 {
803 this->__assign_from(__v);
804 return *this;
805 }
806
807 // LWG2756
Eric Fiselier3906a132019-06-23 20:28:29 +0000808 template <class _Up, _EnableIf<
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000809 _CheckOptionalLikeCtor<_Up, _Up &&>::template __enable_assign<_Up>()
810 , int> = 0>
811 _LIBCPP_INLINE_VISIBILITY
812 optional&
813 operator=(optional<_Up>&& __v)
814 {
815 this->__assign_from(_VSTD::move(__v));
816 return *this;
817 }
818
819 template <class... _Args,
Eric Fiselier3906a132019-06-23 20:28:29 +0000820 class = _EnableIf
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000821 <
822 is_constructible_v<value_type, _Args...>
823 >
824 >
825 _LIBCPP_INLINE_VISIBILITY
Marshall Clow45ff9822017-04-12 22:51:27 +0000826 _Tp &
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000827 emplace(_Args&&... __args)
828 {
829 reset();
830 this->__construct(_VSTD::forward<_Args>(__args)...);
Marshall Clow45ff9822017-04-12 22:51:27 +0000831 return this->__get();
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000832 }
833
834 template <class _Up, class... _Args,
Eric Fiselier3906a132019-06-23 20:28:29 +0000835 class = _EnableIf
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000836 <
837 is_constructible_v<value_type, initializer_list<_Up>&, _Args...>
838 >
839 >
840 _LIBCPP_INLINE_VISIBILITY
Marshall Clow45ff9822017-04-12 22:51:27 +0000841 _Tp &
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000842 emplace(initializer_list<_Up> __il, _Args&&... __args)
843 {
844 reset();
845 this->__construct(__il, _VSTD::forward<_Args>(__args)...);
Marshall Clow45ff9822017-04-12 22:51:27 +0000846 return this->__get();
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000847 }
848
849 _LIBCPP_INLINE_VISIBILITY
850 void swap(optional& __opt)
851 noexcept(is_nothrow_move_constructible_v<value_type> &&
852 is_nothrow_swappable_v<value_type>)
853 {
854 if (this->has_value() == __opt.has_value())
855 {
856 using _VSTD::swap;
857 if (this->has_value())
858 swap(this->__get(), __opt.__get());
859 }
860 else
861 {
862 if (this->has_value())
863 {
864 __opt.__construct(_VSTD::move(this->__get()));
865 reset();
866 }
867 else
868 {
869 this->__construct(_VSTD::move(__opt.__get()));
870 __opt.reset();
871 }
872 }
873 }
874
875 _LIBCPP_INLINE_VISIBILITY
876 constexpr
877 add_pointer_t<value_type const>
878 operator->() const
879 {
880 _LIBCPP_ASSERT(this->has_value(), "optional operator-> called for disengaged value");
881#ifndef _LIBCPP_HAS_NO_BUILTIN_ADDRESSOF
882 return _VSTD::addressof(this->__get());
883#else
884 return __operator_arrow(__has_operator_addressof<value_type>{}, this->__get());
885#endif
886 }
887
888 _LIBCPP_INLINE_VISIBILITY
889 constexpr
890 add_pointer_t<value_type>
891 operator->()
892 {
893 _LIBCPP_ASSERT(this->has_value(), "optional operator-> called for disengaged value");
894#ifndef _LIBCPP_HAS_NO_BUILTIN_ADDRESSOF
895 return _VSTD::addressof(this->__get());
896#else
897 return __operator_arrow(__has_operator_addressof<value_type>{}, this->__get());
898#endif
899 }
900
901 _LIBCPP_INLINE_VISIBILITY
902 constexpr
903 const value_type&
904 operator*() const&
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 this->__get();
917 }
918
919 _LIBCPP_INLINE_VISIBILITY
920 constexpr
921 value_type&&
922 operator*() &&
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
930 const value_type&&
931 operator*() const&&
932 {
933 _LIBCPP_ASSERT(this->has_value(), "optional operator* called for disengaged value");
934 return _VSTD::move(this->__get());
935 }
936
937 _LIBCPP_INLINE_VISIBILITY
938 constexpr explicit operator bool() const noexcept { return has_value(); }
939
940 using __base::has_value;
941 using __base::__get;
942
943 _LIBCPP_INLINE_VISIBILITY
Louis Dionnecef92e62018-11-19 15:37:04 +0000944 _LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000945 constexpr value_type const& value() const&
946 {
947 if (!this->has_value())
948 __throw_bad_optional_access();
949 return this->__get();
950 }
951
952 _LIBCPP_INLINE_VISIBILITY
Louis Dionnecef92e62018-11-19 15:37:04 +0000953 _LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000954 constexpr value_type& value() &
955 {
956 if (!this->has_value())
957 __throw_bad_optional_access();
958 return this->__get();
959 }
960
961 _LIBCPP_INLINE_VISIBILITY
Louis Dionnecef92e62018-11-19 15:37:04 +0000962 _LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000963 constexpr value_type&& value() &&
964 {
965 if (!this->has_value())
966 __throw_bad_optional_access();
967 return _VSTD::move(this->__get());
968 }
969
970 _LIBCPP_INLINE_VISIBILITY
Louis Dionnecef92e62018-11-19 15:37:04 +0000971 _LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000972 constexpr value_type const&& value() const&&
973 {
974 if (!this->has_value())
975 __throw_bad_optional_access();
976 return _VSTD::move(this->__get());
977 }
978
979 template <class _Up>
980 _LIBCPP_INLINE_VISIBILITY
981 constexpr value_type value_or(_Up&& __v) const&
982 {
983 static_assert(is_copy_constructible_v<value_type>,
984 "optional<T>::value_or: T must be copy constructible");
985 static_assert(is_convertible_v<_Up, value_type>,
986 "optional<T>::value_or: U must be convertible to T");
987 return this->has_value() ? this->__get() :
988 static_cast<value_type>(_VSTD::forward<_Up>(__v));
989 }
990
991 template <class _Up>
992 _LIBCPP_INLINE_VISIBILITY
Casey Cartercb05fae2017-06-06 18:47:26 +0000993 constexpr value_type value_or(_Up&& __v) &&
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000994 {
995 static_assert(is_move_constructible_v<value_type>,
996 "optional<T>::value_or: T must be move constructible");
997 static_assert(is_convertible_v<_Up, value_type>,
998 "optional<T>::value_or: U must be convertible to T");
999 return this->has_value() ? _VSTD::move(this->__get()) :
1000 static_cast<value_type>(_VSTD::forward<_Up>(__v));
1001 }
1002
1003 using __base::reset;
1004
1005private:
1006 template <class _Up>
1007 _LIBCPP_INLINE_VISIBILITY
1008 static _Up*
1009 __operator_arrow(true_type, _Up& __x)
1010 {
1011 return _VSTD::addressof(__x);
1012 }
1013
1014 template <class _Up>
1015 _LIBCPP_INLINE_VISIBILITY
1016 static constexpr _Up*
1017 __operator_arrow(false_type, _Up& __x)
1018 {
1019 return &__x;
1020 }
1021};
1022
Marshall Clowe3c71ae2018-05-25 02:08:49 +00001023#ifndef _LIBCPP_HAS_NO_DEDUCTION_GUIDES
1024template<class T>
1025 optional(T) -> optional<T>;
1026#endif
1027
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001028// Comparisons between optionals
Eric Fiselier8af90142017-03-30 20:06:52 +00001029template <class _Tp, class _Up>
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001030_LIBCPP_INLINE_VISIBILITY constexpr
Eric Fiselier3906a132019-06-23 20:28:29 +00001031_EnableIf<
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001032 is_convertible_v<decltype(_VSTD::declval<const _Tp&>() ==
Eric Fiselier8af90142017-03-30 20:06:52 +00001033 _VSTD::declval<const _Up&>()), bool>,
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001034 bool
1035>
Eric Fiselier8af90142017-03-30 20:06:52 +00001036operator==(const optional<_Tp>& __x, const optional<_Up>& __y)
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001037{
1038 if (static_cast<bool>(__x) != static_cast<bool>(__y))
1039 return false;
1040 if (!static_cast<bool>(__x))
1041 return true;
1042 return *__x == *__y;
1043}
1044
Eric Fiselier8af90142017-03-30 20:06:52 +00001045template <class _Tp, class _Up>
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001046_LIBCPP_INLINE_VISIBILITY constexpr
Eric Fiselier3906a132019-06-23 20:28:29 +00001047_EnableIf<
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001048 is_convertible_v<decltype(_VSTD::declval<const _Tp&>() !=
Eric Fiselier8af90142017-03-30 20:06:52 +00001049 _VSTD::declval<const _Up&>()), bool>,
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001050 bool
1051>
Eric Fiselier8af90142017-03-30 20:06:52 +00001052operator!=(const optional<_Tp>& __x, const optional<_Up>& __y)
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001053{
1054 if (static_cast<bool>(__x) != static_cast<bool>(__y))
1055 return true;
1056 if (!static_cast<bool>(__x))
1057 return false;
1058 return *__x != *__y;
1059}
1060
Eric Fiselier8af90142017-03-30 20:06:52 +00001061template <class _Tp, class _Up>
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001062_LIBCPP_INLINE_VISIBILITY constexpr
Eric Fiselier3906a132019-06-23 20:28:29 +00001063_EnableIf<
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001064 is_convertible_v<decltype(_VSTD::declval<const _Tp&>() <
Eric Fiselier8af90142017-03-30 20:06:52 +00001065 _VSTD::declval<const _Up&>()), bool>,
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001066 bool
1067>
Eric Fiselier8af90142017-03-30 20:06:52 +00001068operator<(const optional<_Tp>& __x, const optional<_Up>& __y)
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001069{
1070 if (!static_cast<bool>(__y))
1071 return false;
1072 if (!static_cast<bool>(__x))
1073 return true;
1074 return *__x < *__y;
1075}
1076
Eric Fiselier8af90142017-03-30 20:06:52 +00001077template <class _Tp, class _Up>
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001078_LIBCPP_INLINE_VISIBILITY constexpr
Eric Fiselier3906a132019-06-23 20:28:29 +00001079_EnableIf<
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001080 is_convertible_v<decltype(_VSTD::declval<const _Tp&>() >
Eric Fiselier8af90142017-03-30 20:06:52 +00001081 _VSTD::declval<const _Up&>()), bool>,
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001082 bool
1083>
Eric Fiselier8af90142017-03-30 20:06:52 +00001084operator>(const optional<_Tp>& __x, const optional<_Up>& __y)
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001085{
1086 if (!static_cast<bool>(__x))
1087 return false;
1088 if (!static_cast<bool>(__y))
1089 return true;
1090 return *__x > *__y;
1091}
1092
Eric Fiselier8af90142017-03-30 20:06:52 +00001093template <class _Tp, class _Up>
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001094_LIBCPP_INLINE_VISIBILITY constexpr
Eric Fiselier3906a132019-06-23 20:28:29 +00001095_EnableIf<
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001096 is_convertible_v<decltype(_VSTD::declval<const _Tp&>() <=
Eric Fiselier8af90142017-03-30 20:06:52 +00001097 _VSTD::declval<const _Up&>()), bool>,
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001098 bool
1099>
Eric Fiselier8af90142017-03-30 20:06:52 +00001100operator<=(const optional<_Tp>& __x, const optional<_Up>& __y)
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001101{
1102 if (!static_cast<bool>(__x))
1103 return true;
1104 if (!static_cast<bool>(__y))
1105 return false;
1106 return *__x <= *__y;
1107}
1108
Eric Fiselier8af90142017-03-30 20:06:52 +00001109template <class _Tp, class _Up>
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001110_LIBCPP_INLINE_VISIBILITY constexpr
Eric Fiselier3906a132019-06-23 20:28:29 +00001111_EnableIf<
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001112 is_convertible_v<decltype(_VSTD::declval<const _Tp&>() >=
Eric Fiselier8af90142017-03-30 20:06:52 +00001113 _VSTD::declval<const _Up&>()), bool>,
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001114 bool
1115>
Eric Fiselier8af90142017-03-30 20:06:52 +00001116operator>=(const optional<_Tp>& __x, const optional<_Up>& __y)
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001117{
1118 if (!static_cast<bool>(__y))
1119 return true;
1120 if (!static_cast<bool>(__x))
1121 return false;
1122 return *__x >= *__y;
1123}
1124
1125// Comparisons with nullopt
1126template <class _Tp>
1127_LIBCPP_INLINE_VISIBILITY constexpr
1128bool
1129operator==(const optional<_Tp>& __x, nullopt_t) noexcept
1130{
1131 return !static_cast<bool>(__x);
1132}
1133
1134template <class _Tp>
1135_LIBCPP_INLINE_VISIBILITY constexpr
1136bool
1137operator==(nullopt_t, const optional<_Tp>& __x) noexcept
1138{
1139 return !static_cast<bool>(__x);
1140}
1141
1142template <class _Tp>
1143_LIBCPP_INLINE_VISIBILITY constexpr
1144bool
1145operator!=(const optional<_Tp>& __x, nullopt_t) noexcept
1146{
1147 return static_cast<bool>(__x);
1148}
1149
1150template <class _Tp>
1151_LIBCPP_INLINE_VISIBILITY constexpr
1152bool
1153operator!=(nullopt_t, const optional<_Tp>& __x) noexcept
1154{
1155 return static_cast<bool>(__x);
1156}
1157
1158template <class _Tp>
1159_LIBCPP_INLINE_VISIBILITY constexpr
1160bool
1161operator<(const optional<_Tp>&, nullopt_t) noexcept
1162{
1163 return false;
1164}
1165
1166template <class _Tp>
1167_LIBCPP_INLINE_VISIBILITY constexpr
1168bool
1169operator<(nullopt_t, const optional<_Tp>& __x) noexcept
1170{
1171 return static_cast<bool>(__x);
1172}
1173
1174template <class _Tp>
1175_LIBCPP_INLINE_VISIBILITY constexpr
1176bool
1177operator<=(const optional<_Tp>& __x, nullopt_t) noexcept
1178{
1179 return !static_cast<bool>(__x);
1180}
1181
1182template <class _Tp>
1183_LIBCPP_INLINE_VISIBILITY constexpr
1184bool
Eric Fiselier6003c772016-12-23 23:37:52 +00001185operator<=(nullopt_t, const optional<_Tp>&) noexcept
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001186{
1187 return true;
1188}
1189
1190template <class _Tp>
1191_LIBCPP_INLINE_VISIBILITY constexpr
1192bool
1193operator>(const optional<_Tp>& __x, nullopt_t) noexcept
1194{
1195 return static_cast<bool>(__x);
1196}
1197
1198template <class _Tp>
1199_LIBCPP_INLINE_VISIBILITY constexpr
1200bool
Eric Fiselier6003c772016-12-23 23:37:52 +00001201operator>(nullopt_t, const optional<_Tp>&) noexcept
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001202{
1203 return false;
1204}
1205
1206template <class _Tp>
1207_LIBCPP_INLINE_VISIBILITY constexpr
1208bool
1209operator>=(const optional<_Tp>&, nullopt_t) noexcept
1210{
1211 return true;
1212}
1213
1214template <class _Tp>
1215_LIBCPP_INLINE_VISIBILITY constexpr
1216bool
1217operator>=(nullopt_t, const optional<_Tp>& __x) noexcept
1218{
1219 return !static_cast<bool>(__x);
1220}
1221
1222// Comparisons with T
Eric Fiselier8af90142017-03-30 20:06:52 +00001223template <class _Tp, class _Up>
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001224_LIBCPP_INLINE_VISIBILITY constexpr
Eric Fiselier3906a132019-06-23 20:28:29 +00001225_EnableIf<
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001226 is_convertible_v<decltype(_VSTD::declval<const _Tp&>() ==
Eric Fiselier8af90142017-03-30 20:06:52 +00001227 _VSTD::declval<const _Up&>()), bool>,
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001228 bool
1229>
Eric Fiselier8af90142017-03-30 20:06:52 +00001230operator==(const optional<_Tp>& __x, const _Up& __v)
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001231{
1232 return static_cast<bool>(__x) ? *__x == __v : false;
1233}
1234
Eric Fiselier8af90142017-03-30 20:06:52 +00001235template <class _Tp, class _Up>
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001236_LIBCPP_INLINE_VISIBILITY constexpr
Eric Fiselier3906a132019-06-23 20:28:29 +00001237_EnableIf<
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001238 is_convertible_v<decltype(_VSTD::declval<const _Tp&>() ==
Eric Fiselier8af90142017-03-30 20:06:52 +00001239 _VSTD::declval<const _Up&>()), bool>,
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001240 bool
1241>
Eric Fiselier8af90142017-03-30 20:06:52 +00001242operator==(const _Tp& __v, const optional<_Up>& __x)
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001243{
1244 return static_cast<bool>(__x) ? __v == *__x : false;
1245}
1246
Eric Fiselier8af90142017-03-30 20:06:52 +00001247template <class _Tp, class _Up>
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001248_LIBCPP_INLINE_VISIBILITY constexpr
Eric Fiselier3906a132019-06-23 20:28:29 +00001249_EnableIf<
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001250 is_convertible_v<decltype(_VSTD::declval<const _Tp&>() !=
Eric Fiselier8af90142017-03-30 20:06:52 +00001251 _VSTD::declval<const _Up&>()), bool>,
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001252 bool
1253>
Eric Fiselier8af90142017-03-30 20:06:52 +00001254operator!=(const optional<_Tp>& __x, const _Up& __v)
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001255{
1256 return static_cast<bool>(__x) ? *__x != __v : true;
1257}
1258
Eric Fiselier8af90142017-03-30 20:06:52 +00001259template <class _Tp, class _Up>
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001260_LIBCPP_INLINE_VISIBILITY constexpr
Eric Fiselier3906a132019-06-23 20:28:29 +00001261_EnableIf<
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001262 is_convertible_v<decltype(_VSTD::declval<const _Tp&>() !=
Eric Fiselier8af90142017-03-30 20:06:52 +00001263 _VSTD::declval<const _Up&>()), bool>,
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001264 bool
1265>
Eric Fiselier8af90142017-03-30 20:06:52 +00001266operator!=(const _Tp& __v, const optional<_Up>& __x)
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001267{
1268 return static_cast<bool>(__x) ? __v != *__x : true;
1269}
1270
Eric Fiselier8af90142017-03-30 20:06:52 +00001271template <class _Tp, class _Up>
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001272_LIBCPP_INLINE_VISIBILITY constexpr
Eric Fiselier3906a132019-06-23 20:28:29 +00001273_EnableIf<
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001274 is_convertible_v<decltype(_VSTD::declval<const _Tp&>() <
Eric Fiselier8af90142017-03-30 20:06:52 +00001275 _VSTD::declval<const _Up&>()), bool>,
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001276 bool
1277>
Eric Fiselier8af90142017-03-30 20:06:52 +00001278operator<(const optional<_Tp>& __x, const _Up& __v)
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001279{
1280 return static_cast<bool>(__x) ? *__x < __v : true;
1281}
1282
Eric Fiselier8af90142017-03-30 20:06:52 +00001283template <class _Tp, class _Up>
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001284_LIBCPP_INLINE_VISIBILITY constexpr
Eric Fiselier3906a132019-06-23 20:28:29 +00001285_EnableIf<
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001286 is_convertible_v<decltype(_VSTD::declval<const _Tp&>() <
Eric Fiselier8af90142017-03-30 20:06:52 +00001287 _VSTD::declval<const _Up&>()), bool>,
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001288 bool
1289>
Eric Fiselier8af90142017-03-30 20:06:52 +00001290operator<(const _Tp& __v, const optional<_Up>& __x)
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001291{
1292 return static_cast<bool>(__x) ? __v < *__x : false;
1293}
1294
Eric Fiselier8af90142017-03-30 20:06:52 +00001295template <class _Tp, class _Up>
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001296_LIBCPP_INLINE_VISIBILITY constexpr
Eric Fiselier3906a132019-06-23 20:28:29 +00001297_EnableIf<
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001298 is_convertible_v<decltype(_VSTD::declval<const _Tp&>() <=
Eric Fiselier8af90142017-03-30 20:06:52 +00001299 _VSTD::declval<const _Up&>()), bool>,
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001300 bool
1301>
Eric Fiselier8af90142017-03-30 20:06:52 +00001302operator<=(const optional<_Tp>& __x, const _Up& __v)
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001303{
1304 return static_cast<bool>(__x) ? *__x <= __v : true;
1305}
1306
Eric Fiselier8af90142017-03-30 20:06:52 +00001307template <class _Tp, class _Up>
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001308_LIBCPP_INLINE_VISIBILITY constexpr
Eric Fiselier3906a132019-06-23 20:28:29 +00001309_EnableIf<
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001310 is_convertible_v<decltype(_VSTD::declval<const _Tp&>() <=
Eric Fiselier8af90142017-03-30 20:06:52 +00001311 _VSTD::declval<const _Up&>()), bool>,
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001312 bool
1313>
Eric Fiselier8af90142017-03-30 20:06:52 +00001314operator<=(const _Tp& __v, const optional<_Up>& __x)
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001315{
1316 return static_cast<bool>(__x) ? __v <= *__x : false;
1317}
1318
Eric Fiselier8af90142017-03-30 20:06:52 +00001319template <class _Tp, class _Up>
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001320_LIBCPP_INLINE_VISIBILITY constexpr
Eric Fiselier3906a132019-06-23 20:28:29 +00001321_EnableIf<
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001322 is_convertible_v<decltype(_VSTD::declval<const _Tp&>() >
Eric Fiselier8af90142017-03-30 20:06:52 +00001323 _VSTD::declval<const _Up&>()), bool>,
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001324 bool
1325>
Eric Fiselier8af90142017-03-30 20:06:52 +00001326operator>(const optional<_Tp>& __x, const _Up& __v)
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001327{
1328 return static_cast<bool>(__x) ? *__x > __v : false;
1329}
1330
Eric Fiselier8af90142017-03-30 20:06:52 +00001331template <class _Tp, class _Up>
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001332_LIBCPP_INLINE_VISIBILITY constexpr
Eric Fiselier3906a132019-06-23 20:28:29 +00001333_EnableIf<
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001334 is_convertible_v<decltype(_VSTD::declval<const _Tp&>() >
Eric Fiselier8af90142017-03-30 20:06:52 +00001335 _VSTD::declval<const _Up&>()), bool>,
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001336 bool
1337>
Eric Fiselier8af90142017-03-30 20:06:52 +00001338operator>(const _Tp& __v, const optional<_Up>& __x)
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001339{
1340 return static_cast<bool>(__x) ? __v > *__x : true;
1341}
1342
Eric Fiselier8af90142017-03-30 20:06:52 +00001343template <class _Tp, class _Up>
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001344_LIBCPP_INLINE_VISIBILITY constexpr
Eric Fiselier3906a132019-06-23 20:28:29 +00001345_EnableIf<
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001346 is_convertible_v<decltype(_VSTD::declval<const _Tp&>() >=
Eric Fiselier8af90142017-03-30 20:06:52 +00001347 _VSTD::declval<const _Up&>()), bool>,
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001348 bool
1349>
Eric Fiselier8af90142017-03-30 20:06:52 +00001350operator>=(const optional<_Tp>& __x, const _Up& __v)
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001351{
1352 return static_cast<bool>(__x) ? *__x >= __v : false;
1353}
1354
Eric Fiselier8af90142017-03-30 20:06:52 +00001355template <class _Tp, class _Up>
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001356_LIBCPP_INLINE_VISIBILITY constexpr
Eric Fiselier3906a132019-06-23 20:28:29 +00001357_EnableIf<
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001358 is_convertible_v<decltype(_VSTD::declval<const _Tp&>() >=
Eric Fiselier8af90142017-03-30 20:06:52 +00001359 _VSTD::declval<const _Up&>()), bool>,
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001360 bool
1361>
Eric Fiselier8af90142017-03-30 20:06:52 +00001362operator>=(const _Tp& __v, const optional<_Up>& __x)
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001363{
1364 return static_cast<bool>(__x) ? __v >= *__x : true;
1365}
1366
1367
1368template <class _Tp>
1369inline _LIBCPP_INLINE_VISIBILITY
Eric Fiselier3906a132019-06-23 20:28:29 +00001370_EnableIf<
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001371 is_move_constructible_v<_Tp> && is_swappable_v<_Tp>,
1372 void
1373>
1374swap(optional<_Tp>& __x, optional<_Tp>& __y) noexcept(noexcept(__x.swap(__y)))
1375{
1376 __x.swap(__y);
1377}
1378
1379template <class _Tp>
1380_LIBCPP_INLINE_VISIBILITY constexpr
1381optional<decay_t<_Tp>> make_optional(_Tp&& __v)
1382{
1383 return optional<decay_t<_Tp>>(_VSTD::forward<_Tp>(__v));
1384}
1385
1386template <class _Tp, class... _Args>
1387_LIBCPP_INLINE_VISIBILITY constexpr
1388optional<_Tp> make_optional(_Args&&... __args)
1389{
1390 return optional<_Tp>(in_place, _VSTD::forward<_Args>(__args)...);
1391}
1392
1393template <class _Tp, class _Up, class... _Args>
1394_LIBCPP_INLINE_VISIBILITY constexpr
1395optional<_Tp> make_optional(initializer_list<_Up> __il, _Args&&... __args)
1396{
1397 return optional<_Tp>(in_place, __il, _VSTD::forward<_Args>(__args)...);
1398}
1399
1400template <class _Tp>
Eric Fiselier698a97b2017-01-21 00:02:12 +00001401struct _LIBCPP_TEMPLATE_VIS hash<
1402 __enable_hash_helper<optional<_Tp>, remove_const_t<_Tp>>
1403>
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001404{
1405 typedef optional<_Tp> argument_type;
1406 typedef size_t result_type;
1407
1408 _LIBCPP_INLINE_VISIBILITY
Marshall Clow49036892017-03-23 02:40:28 +00001409 result_type operator()(const argument_type& __opt) const
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001410 {
Eric Fiselier698a97b2017-01-21 00:02:12 +00001411 return static_cast<bool>(__opt) ? hash<remove_const_t<_Tp>>()(*__opt) : 0;
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001412 }
1413};
1414
1415_LIBCPP_END_NAMESPACE_STD
1416
1417#endif // _LIBCPP_STD_VER > 14
1418
Eric Fiselierf4433a32017-05-31 22:07:49 +00001419_LIBCPP_POP_MACROS
1420
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001421#endif // _LIBCPP_OPTIONAL