blob: 3848da872b8bcc1270dd2a481f096774e032902d [file] [log] [blame]
Howard Hinnante7d746d2013-09-02 20:30:37 +00001// -*- C++ -*-
2//===-------------------------- optional ----------------------------------===//
3//
4// The LLVM Compiler Infrastructure
5//
6// This file is dual licensed under the MIT and the University of Illinois Open
7// Source Licenses. See LICENSE.TXT for details.
8//
9//===----------------------------------------------------------------------===//
10
11#ifndef _LIBCPP_OPTIONAL
12#define _LIBCPP_OPTIONAL
13
14/*
15 optional synopsis
16
17// C++1y
18
19#include <initializer_list>
20
Marshall Clowdfdac032013-11-15 22:42:10 +000021namespace std { namespace experimental {
Howard Hinnante7d746d2013-09-02 20:30:37 +000022
23// optional for object types
24template <class T>
25class optional
26{
27public:
28 typedef T value_type;
29
30 // constructors
31 constexpr optional() noexcept;
32 constexpr optional(nullopt_t) noexcept;
33 optional(const optional&);
34 optional(optional&&) noexcept(is_nothrow_move_constructible<T>::value);
35 constexpr optional(const T&);
36 constexpr optional(T&&);
37 template <class... Args> constexpr explicit optional(in_place_t, Args&&...);
38 template <class U, class... Args>
39 constexpr explicit optional(in_place_t, initializer_list<U>, Args&&...);
40
41 // destructor
42 ~optional();
43
44 // assignment
45 optional& operator=(nullopt_t) noexcept;
46 optional& operator=(const optional&);
47 optional& operator=(optional&&)
48 noexcept(is_nothrow_move_assignable<T>::value &&
49 is_nothrow_move_constructible<T>::value);
50 template <class U> optional& operator=(U&&);
51 template <class... Args> void emplace(Args&&...);
52 template <class U, class... Args> void emplace(initializer_list<U>, Args&&...);
53
54 // swap
55 void swap(optional&)
56 noexcept(is_nothrow_move_constructible<T>::value &&
57 noexcept(swap(declval<T&>(), declval<T&>())));
58
59 // observers
60 constexpr T const* operator->() const;
61 T* operator->();
62 constexpr T const& operator*() const;
63 T& operator*();
64 constexpr explicit operator bool() const noexcept;
65 constexpr T const& value() const;
66 T& value();
67 template <class U> constexpr T value_or(U&&) const&;
68 template <class U> T value_or(U&&) &&;
69};
70
71// In-place construction
72struct in_place_t{};
73constexpr in_place_t in_place{};
74
75// Disengaged state indicator
76struct nullopt_t{see below};
77constexpr nullopt_t nullopt(unspecified);
78
79// class bad_optional_access
80class bad_optional_access
81 : public logic_error
82{
83public:
84 explicit bad_optional_access(const string& what_arg);
85 explicit bad_optional_access(const char* what_arg);
86};
87
88// Relational operators
89template <class T> constexpr bool operator==(const optional<T>&, const optional<T>&);
90template <class T> constexpr bool operator< (const optional<T>&, const optional<T>&);
91
92// Comparison with nullopt
93template <class T> constexpr bool operator==(const optional<T>&, nullopt_t) noexcept;
94template <class T> constexpr bool operator==(nullopt_t, const optional<T>&) noexcept;
95template <class T> constexpr bool operator<(const optional<T>&, nullopt_t) noexcept;
96template <class T> constexpr bool operator<(nullopt_t, const optional<T>&) noexcept;
97
98// Comparison with T
99template <class T> constexpr bool operator==(const optional<T>&, const T&);
100template <class T> constexpr bool operator==(const T&, const optional<T>&);
101template <class T> constexpr bool operator<(const optional<T>&, const T&);
102template <class T> constexpr bool operator<(const T&, const optional<T>&);
103
104// Specialized algorithms
105template <class T> void swap(optional<T>&, optional<T>&) noexcept(see below);
106template <class T> constexpr optional<typename decay<T>::type> make_optional(T&&);
107
108// hash support
109template <class T> struct hash;
110template <class T> struct hash<optional<T>>;
111
Marshall Clowdfdac032013-11-15 22:42:10 +0000112}} // std::experimental
Howard Hinnante7d746d2013-09-02 20:30:37 +0000113
114*/
115
116#include <__config>
117#include <functional>
118#include <stdexcept>
119
Marshall Clowdfdac032013-11-15 22:42:10 +0000120namespace std { namespace experimental {
Howard Hinnante7d746d2013-09-02 20:30:37 +0000121
122class _LIBCPP_EXCEPTION_ABI bad_optional_access
123 : public logic_error
124{
125public:
126#if _LIBCPP_STD_VER > 11
127 _LIBCPP_INLINE_VISIBILITY explicit bad_optional_access(const string& __arg)
128 : logic_error(__arg) {}
129 _LIBCPP_INLINE_VISIBILITY explicit bad_optional_access(const char* __arg)
130 : logic_error(__arg) {}
131 _LIBCPP_INLINE_VISIBILITY bad_optional_access(const bad_optional_access&) noexcept = default;
132 _LIBCPP_INLINE_VISIBILITY bad_optional_access& operator=(const bad_optional_access&) noexcept = default;
133#else
134private:
135 bad_optional_access(const bad_optional_access&);
136 bad_optional_access& operator=(const bad_optional_access&);
137public:
138#endif // _LIBCPP_STD_VER > 11
139 // Get the key function ~bad_optional_access() into the dylib even if not compiling for C++1y
140 virtual ~bad_optional_access() _NOEXCEPT;
141};
142
Marshall Clowdfdac032013-11-15 22:42:10 +0000143}} // std::experimental
Howard Hinnante7d746d2013-09-02 20:30:37 +0000144
145#if _LIBCPP_STD_VER > 11
146
147#include <initializer_list>
148#include <type_traits>
149#include <new>
150#include <__functional_base>
151
152#include <__undef_min_max>
153
154#ifdef _LIBCPP_DEBUG
155# include <__debug>
156#else
157# define _LIBCPP_ASSERT(x, m) ((void)0)
158#endif
159
160#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
161#pragma GCC system_header
162#endif
163
Marshall Clowdfdac032013-11-15 22:42:10 +0000164namespace std { namespace experimental { inline namespace __library_fundamentals_v1 {
Howard Hinnante7d746d2013-09-02 20:30:37 +0000165
166struct in_place_t {};
167constexpr in_place_t in_place{};
168
169struct nullopt_t
170{
171 explicit constexpr nullopt_t(int) noexcept {}
172};
173
174constexpr nullopt_t nullopt{0};
175
176template <class _Tp, bool = is_trivially_destructible<_Tp>::value>
177class __optional_storage
178{
179protected:
180 typedef _Tp value_type;
181 union
182 {
183 char __null_state_;
184 value_type __val_;
185 };
186 bool __engaged_ = false;
187
188 _LIBCPP_INLINE_VISIBILITY
189 ~__optional_storage()
190 {
191 if (__engaged_)
192 __val_.~value_type();
193 }
194
195 _LIBCPP_INLINE_VISIBILITY
196 constexpr __optional_storage() noexcept
197 : __null_state_('\0') {}
198
199 _LIBCPP_INLINE_VISIBILITY
200 __optional_storage(const __optional_storage& __x)
201 : __engaged_(__x.__engaged_)
202 {
203 if (__engaged_)
204 ::new(_VSTD::addressof(__val_)) value_type(__x.__val_);
205 }
206
207 _LIBCPP_INLINE_VISIBILITY
208 __optional_storage(__optional_storage&& __x)
209 noexcept(is_nothrow_move_constructible<value_type>::value)
210 : __engaged_(__x.__engaged_)
211 {
212 if (__engaged_)
213 ::new(_VSTD::addressof(__val_)) value_type(_VSTD::move(__x.__val_));
214 }
215
216 _LIBCPP_INLINE_VISIBILITY
217 constexpr __optional_storage(const value_type& __v)
218 : __val_(__v),
219 __engaged_(true) {}
220
221 _LIBCPP_INLINE_VISIBILITY
222 constexpr __optional_storage(value_type&& __v)
223 : __val_(_VSTD::move(__v)),
224 __engaged_(true) {}
225
226 template <class... _Args>
227 _LIBCPP_INLINE_VISIBILITY
228 constexpr
229 explicit __optional_storage(in_place_t, _Args&&... __args)
230 : __val_(_VSTD::forward<_Args>(__args)...),
231 __engaged_(true) {}
232};
233
234template <class _Tp>
235class __optional_storage<_Tp, true>
236{
237protected:
238 typedef _Tp value_type;
239 union
240 {
241 char __null_state_;
242 value_type __val_;
243 };
244 bool __engaged_ = false;
245
246 _LIBCPP_INLINE_VISIBILITY
247 constexpr __optional_storage() noexcept
248 : __null_state_('\0') {}
249
250 _LIBCPP_INLINE_VISIBILITY
251 __optional_storage(const __optional_storage& __x)
252 : __engaged_(__x.__engaged_)
253 {
254 if (__engaged_)
255 ::new(_VSTD::addressof(__val_)) value_type(__x.__val_);
256 }
257
258 _LIBCPP_INLINE_VISIBILITY
259 __optional_storage(__optional_storage&& __x)
260 noexcept(is_nothrow_move_constructible<value_type>::value)
261 : __engaged_(__x.__engaged_)
262 {
263 if (__engaged_)
264 ::new(_VSTD::addressof(__val_)) value_type(_VSTD::move(__x.__val_));
265 }
266
267 _LIBCPP_INLINE_VISIBILITY
268 constexpr __optional_storage(const value_type& __v)
269 : __val_(__v),
270 __engaged_(true) {}
271
272 _LIBCPP_INLINE_VISIBILITY
273 constexpr __optional_storage(value_type&& __v)
274 : __val_(_VSTD::move(__v)),
275 __engaged_(true) {}
276
277 template <class... _Args>
278 _LIBCPP_INLINE_VISIBILITY
279 constexpr
280 explicit __optional_storage(in_place_t, _Args&&... __args)
281 : __val_(_VSTD::forward<_Args>(__args)...),
282 __engaged_(true) {}
283};
284
285template <class _Tp>
286class optional
287 : private __optional_storage<_Tp>
288{
289 typedef __optional_storage<_Tp> __base;
290public:
291 typedef _Tp value_type;
292
293 static_assert(!is_reference<value_type>::value,
294 "Instantiation of optional with a reference type is ill-formed.");
295 static_assert(!is_same<typename remove_cv<value_type>::type, in_place_t>::value,
296 "Instantiation of optional with a in_place_t type is ill-formed.");
297 static_assert(!is_same<typename remove_cv<value_type>::type, nullopt_t>::value,
298 "Instantiation of optional with a nullopt_t type is ill-formed.");
299 static_assert(is_object<value_type>::value,
300 "Instantiation of optional with a non-object type is undefined behavior.");
301 static_assert(is_nothrow_destructible<value_type>::value,
302 "Instantiation of optional with an object type that is not noexcept destructible is undefined behavior.");
303
304 _LIBCPP_INLINE_VISIBILITY constexpr optional() noexcept {}
305 _LIBCPP_INLINE_VISIBILITY optional(const optional&) = default;
306 _LIBCPP_INLINE_VISIBILITY optional(optional&&) = default;
307 _LIBCPP_INLINE_VISIBILITY ~optional() = default;
308 _LIBCPP_INLINE_VISIBILITY constexpr optional(nullopt_t) noexcept {}
309 _LIBCPP_INLINE_VISIBILITY constexpr optional(const value_type& __v)
310 : __base(__v) {}
311 _LIBCPP_INLINE_VISIBILITY constexpr optional(value_type&& __v)
312 : __base(_VSTD::move(__v)) {}
313
314 template <class... _Args,
315 class = typename enable_if
316 <
317 is_constructible<value_type, _Args...>::value
318 >::type
319 >
320 _LIBCPP_INLINE_VISIBILITY
321 constexpr
322 explicit optional(in_place_t, _Args&&... __args)
323 : __base(in_place, _VSTD::forward<_Args>(__args)...) {}
324
325 template <class _Up, class... _Args,
326 class = typename enable_if
327 <
328 is_constructible<value_type, initializer_list<_Up>&, _Args...>::value
329 >::type
330 >
331 _LIBCPP_INLINE_VISIBILITY
332 constexpr
333 explicit optional(in_place_t, initializer_list<_Up> __il, _Args&&... __args)
334 : __base(in_place, __il, _VSTD::forward<_Args>(__args)...) {}
335
336 _LIBCPP_INLINE_VISIBILITY
337 optional& operator=(nullopt_t) noexcept
338 {
339 if (this->__engaged_)
340 {
341 this->__val_.~value_type();
342 this->__engaged_ = false;
343 }
344 return *this;
345 }
346
347 _LIBCPP_INLINE_VISIBILITY
348 optional&
349 operator=(const optional& __opt)
350 {
351 if (this->__engaged_ == __opt.__engaged_)
352 {
353 if (this->__engaged_)
354 this->__val_ = __opt.__val_;
355 }
356 else
357 {
358 if (this->__engaged_)
359 this->__val_.~value_type();
360 else
361 ::new(_VSTD::addressof(this->__val_)) value_type(__opt.__val_);
362 this->__engaged_ = __opt.__engaged_;
363 }
364 return *this;
365 }
366
367 _LIBCPP_INLINE_VISIBILITY
368 optional&
369 operator=(optional&& __opt)
370 noexcept(is_nothrow_move_assignable<value_type>::value &&
371 is_nothrow_move_constructible<value_type>::value)
372 {
373 if (this->__engaged_ == __opt.__engaged_)
374 {
375 if (this->__engaged_)
376 this->__val_ = _VSTD::move(__opt.__val_);
377 }
378 else
379 {
380 if (this->__engaged_)
381 this->__val_.~value_type();
382 else
383 ::new(_VSTD::addressof(this->__val_)) value_type(_VSTD::move(__opt.__val_));
384 this->__engaged_ = __opt.__engaged_;
385 }
386 return *this;
387 }
388
389 template <class _Up,
390 class = typename enable_if
391 <
392 is_same<typename remove_reference<_Up>::type, value_type>::value &&
393 is_constructible<value_type, _Up>::value &&
394 is_assignable<value_type&, _Up>::value
395 >::type
396 >
397 _LIBCPP_INLINE_VISIBILITY
398 optional&
399 operator=(_Up&& __v)
400 {
401 if (this->__engaged_)
402 this->__val_ = _VSTD::forward<_Up>(__v);
403 else
404 {
405 ::new(_VSTD::addressof(this->__val_)) value_type(_VSTD::forward<_Up>(__v));
406 this->__engaged_ = true;
407 }
408 return *this;
409 }
410
411 template <class... _Args,
412 class = typename enable_if
413 <
414 is_constructible<value_type, _Args...>::value
415 >::type
416 >
417 _LIBCPP_INLINE_VISIBILITY
418 void
419 emplace(_Args&&... __args)
420 {
421 *this = nullopt;
422 ::new(_VSTD::addressof(this->__val_)) value_type(_VSTD::forward<_Args>(__args)...);
423 this->__engaged_ = true;
424 }
425
426 template <class _Up, class... _Args,
427 class = typename enable_if
428 <
429 is_constructible<value_type, initializer_list<_Up>&, _Args...>::value
430 >::type
431 >
432 _LIBCPP_INLINE_VISIBILITY
433 void
434 emplace(initializer_list<_Up> __il, _Args&&... __args)
435 {
436 *this = nullopt;
437 ::new(_VSTD::addressof(this->__val_)) value_type(__il, _VSTD::forward<_Args>(__args)...);
438 this->__engaged_ = true;
439 }
440
441 _LIBCPP_INLINE_VISIBILITY
442 void
443 swap(optional& __opt)
444 noexcept(is_nothrow_move_constructible<value_type>::value &&
445 __is_nothrow_swappable<value_type>::value)
446 {
447 using _VSTD::swap;
448 if (this->__engaged_ == __opt.__engaged_)
449 {
450 if (this->__engaged_)
451 swap(this->__val_, __opt.__val_);
452 }
453 else
454 {
455 if (this->__engaged_)
456 {
457 ::new(_VSTD::addressof(__opt.__val_)) value_type(_VSTD::move(this->__val_));
458 this->__val_.~value_type();
459 }
460 else
461 {
462 ::new(_VSTD::addressof(this->__val_)) value_type(_VSTD::move(__opt.__val_));
463 __opt.__val_.~value_type();
464 }
465 swap(this->__engaged_, __opt.__engaged_);
466 }
467 }
468
469 _LIBCPP_INLINE_VISIBILITY
470 constexpr
471 value_type const*
472 operator->() const
473 {
474 _LIBCPP_ASSERT(this->__engaged_, "optional operator-> called for disengaged value");
475 return __operator_arrow(__has_operator_addressof<value_type>{});
476 }
477
478 _LIBCPP_INLINE_VISIBILITY
479 value_type*
480 operator->()
481 {
482 _LIBCPP_ASSERT(this->__engaged_, "optional operator-> called for disengaged value");
483 return _VSTD::addressof(this->__val_);
484 }
485
486 _LIBCPP_INLINE_VISIBILITY
487 constexpr
488 const value_type&
489 operator*() const
490 {
491 _LIBCPP_ASSERT(this->__engaged_, "optional operator* called for disengaged value");
492 return this->__val_;
493 }
494
495 _LIBCPP_INLINE_VISIBILITY
496 value_type&
497 operator*()
498 {
499 _LIBCPP_ASSERT(this->__engaged_, "optional operator* called for disengaged value");
500 return this->__val_;
501 }
502
503 _LIBCPP_INLINE_VISIBILITY
504 constexpr explicit operator bool() const noexcept {return this->__engaged_;}
505
506 _LIBCPP_INLINE_VISIBILITY
507 constexpr value_type const& value() const
508 {
509 if (!this->__engaged_)
510 throw bad_optional_access("optional<T>::value: not engaged");
511 return this->__val_;
512 }
513
514 _LIBCPP_INLINE_VISIBILITY
515 value_type& value()
516 {
517 if (!this->__engaged_)
518 throw bad_optional_access("optional<T>::value: not engaged");
519 return this->__val_;
520 }
521
522 template <class _Up>
523 _LIBCPP_INLINE_VISIBILITY
524 constexpr value_type value_or(_Up&& __v) const&
525 {
526 static_assert(is_copy_constructible<value_type>::value,
527 "optional<T>::value_or: T must be copy constructible");
528 static_assert(is_convertible<_Up, value_type>::value,
529 "optional<T>::value_or: U must be convertible to T");
530 return this->__engaged_ ? this->__val_ :
531 static_cast<value_type>(_VSTD::forward<_Up>(__v));
532 }
533
534 template <class _Up>
535 _LIBCPP_INLINE_VISIBILITY
536 value_type value_or(_Up&& __v) &&
537 {
538 static_assert(is_move_constructible<value_type>::value,
539 "optional<T>::value_or: T must be move constructible");
540 static_assert(is_convertible<_Up, value_type>::value,
541 "optional<T>::value_or: U must be convertible to T");
542 return this->__engaged_ ? _VSTD::move(this->__val_) :
543 static_cast<value_type>(_VSTD::forward<_Up>(__v));
544 }
545
546private:
547 _LIBCPP_INLINE_VISIBILITY
548 value_type const*
549 __operator_arrow(true_type) const
550 {
551 return _VSTD::addressof(this->__val_);
552 }
553
554 _LIBCPP_INLINE_VISIBILITY
555 constexpr
556 value_type const*
557 __operator_arrow(false_type) const
558 {
559 return &this->__val_;
560 }
561};
562
563template <class _Tp>
564inline _LIBCPP_INLINE_VISIBILITY
565constexpr
566bool
567operator==(const optional<_Tp>& __x, const optional<_Tp>& __y)
568{
569 if (static_cast<bool>(__x) != static_cast<bool>(__y))
570 return false;
571 if (!static_cast<bool>(__x))
572 return true;
573 return *__x == *__y;
574}
575
576template <class _Tp>
577inline _LIBCPP_INLINE_VISIBILITY
578constexpr
579bool
580operator<(const optional<_Tp>& __x, const optional<_Tp>& __y)
581{
582 if (!static_cast<bool>(__y))
583 return false;
584 if (!static_cast<bool>(__x))
585 return true;
586 return less<_Tp>{}(*__x, *__y);
587}
588
589template <class _Tp>
590inline _LIBCPP_INLINE_VISIBILITY
591constexpr
592bool
593operator==(const optional<_Tp>& __x, nullopt_t) noexcept
594{
595 return !static_cast<bool>(__x);
596}
597
598template <class _Tp>
599inline _LIBCPP_INLINE_VISIBILITY
600constexpr
601bool
602operator==(nullopt_t, const optional<_Tp>& __x) noexcept
603{
604 return !static_cast<bool>(__x);
605}
606
607template <class _Tp>
608inline _LIBCPP_INLINE_VISIBILITY
609constexpr
610bool
611operator<(const optional<_Tp>&, nullopt_t) noexcept
612{
613 return false;
614}
615
616template <class _Tp>
617inline _LIBCPP_INLINE_VISIBILITY
618constexpr
619bool
620operator<(nullopt_t, const optional<_Tp>& __x) noexcept
621{
622 return static_cast<bool>(__x);
623}
624
625template <class _Tp>
626inline _LIBCPP_INLINE_VISIBILITY
627constexpr
628bool
629operator==(const optional<_Tp>& __x, const _Tp& __v)
630{
631 return static_cast<bool>(__x) ? *__x == __v : false;
632}
633
634template <class _Tp>
635inline _LIBCPP_INLINE_VISIBILITY
636constexpr
637bool
638operator==(const _Tp& __v, const optional<_Tp>& __x)
639{
640 return static_cast<bool>(__x) ? *__x == __v : false;
641}
642
643template <class _Tp>
644inline _LIBCPP_INLINE_VISIBILITY
645constexpr
646bool
647operator<(const optional<_Tp>& __x, const _Tp& __v)
648{
649 return static_cast<bool>(__x) ? less<_Tp>{}(*__x, __v) : true;
650}
651
652template <class _Tp>
653inline _LIBCPP_INLINE_VISIBILITY
654constexpr
655bool
656operator<(const _Tp& __v, const optional<_Tp>& __x)
657{
658 return static_cast<bool>(__x) ? less<_Tp>{}(__v, *__x) : false;
659}
660
661template <class _Tp>
662inline _LIBCPP_INLINE_VISIBILITY
663void
664swap(optional<_Tp>& __x, optional<_Tp>& __y) noexcept(noexcept(__x.swap(__y)))
665{
666 __x.swap(__y);
667}
668
669template <class _Tp>
670inline _LIBCPP_INLINE_VISIBILITY
671constexpr
672optional<typename decay<_Tp>::type>
673make_optional(_Tp&& __v)
674{
675 return optional<typename decay<_Tp>::type>(_VSTD::forward<_Tp>(__v));
676}
677
Marshall Clowdfdac032013-11-15 22:42:10 +0000678}}} // namespace std::experimental::__library_fundamentals_v1
679
680_LIBCPP_BEGIN_NAMESPACE_STD
681
Howard Hinnante7d746d2013-09-02 20:30:37 +0000682template <class _Tp>
Marshall Clowdfdac032013-11-15 22:42:10 +0000683struct _LIBCPP_TYPE_VIS_ONLY hash<std::experimental::optional<_Tp> >
Howard Hinnante7d746d2013-09-02 20:30:37 +0000684{
Marshall Clowdfdac032013-11-15 22:42:10 +0000685 typedef std::experimental::optional<_Tp> argument_type;
Howard Hinnante7d746d2013-09-02 20:30:37 +0000686 typedef size_t result_type;
687
688 _LIBCPP_INLINE_VISIBILITY
689 result_type operator()(const argument_type& __opt) const _NOEXCEPT
690 {
691 return static_cast<bool>(__opt) ? hash<_Tp>()(*__opt) : 0;
692 }
693};
694
695_LIBCPP_END_NAMESPACE_STD
696
697#endif // _LIBCPP_STD_VER > 11
698
699#endif // _LIBCPP_ARRAY