blob: 41d86b4a16954e3f6676d73543dd6730a783b299 [file] [log] [blame]
Howard Hinnant01afa5c2013-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 Clow0cdbe602013-11-15 22:42:10 +000021namespace std { namespace experimental {
Howard Hinnant01afa5c2013-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 Clow0cdbe602013-11-15 22:42:10 +0000112}} // std::experimental
Howard Hinnant01afa5c2013-09-02 20:30:37 +0000113
114*/
115
116#include <__config>
117#include <functional>
118#include <stdexcept>
119
Marshall Clow0cdbe602013-11-15 22:42:10 +0000120namespace std { namespace experimental {
Howard Hinnant01afa5c2013-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 Clow0cdbe602013-11-15 22:42:10 +0000143}} // std::experimental
Howard Hinnant01afa5c2013-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
Eric Fiselierb9536102014-08-10 23:53:08 +0000154#include <__debug>
Howard Hinnant01afa5c2013-09-02 20:30:37 +0000155
156#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
157#pragma GCC system_header
158#endif
159
Marshall Clow0cdbe602013-11-15 22:42:10 +0000160namespace std { namespace experimental { inline namespace __library_fundamentals_v1 {
Howard Hinnant01afa5c2013-09-02 20:30:37 +0000161
162struct in_place_t {};
163constexpr in_place_t in_place{};
164
165struct nullopt_t
166{
167 explicit constexpr nullopt_t(int) noexcept {}
168};
169
170constexpr nullopt_t nullopt{0};
171
172template <class _Tp, bool = is_trivially_destructible<_Tp>::value>
173class __optional_storage
174{
175protected:
176 typedef _Tp value_type;
177 union
178 {
179 char __null_state_;
180 value_type __val_;
181 };
182 bool __engaged_ = false;
183
184 _LIBCPP_INLINE_VISIBILITY
185 ~__optional_storage()
186 {
187 if (__engaged_)
188 __val_.~value_type();
189 }
190
191 _LIBCPP_INLINE_VISIBILITY
192 constexpr __optional_storage() noexcept
193 : __null_state_('\0') {}
194
195 _LIBCPP_INLINE_VISIBILITY
196 __optional_storage(const __optional_storage& __x)
197 : __engaged_(__x.__engaged_)
198 {
199 if (__engaged_)
200 ::new(_VSTD::addressof(__val_)) value_type(__x.__val_);
201 }
202
203 _LIBCPP_INLINE_VISIBILITY
204 __optional_storage(__optional_storage&& __x)
205 noexcept(is_nothrow_move_constructible<value_type>::value)
206 : __engaged_(__x.__engaged_)
207 {
208 if (__engaged_)
209 ::new(_VSTD::addressof(__val_)) value_type(_VSTD::move(__x.__val_));
210 }
211
212 _LIBCPP_INLINE_VISIBILITY
213 constexpr __optional_storage(const value_type& __v)
214 : __val_(__v),
215 __engaged_(true) {}
216
217 _LIBCPP_INLINE_VISIBILITY
218 constexpr __optional_storage(value_type&& __v)
219 : __val_(_VSTD::move(__v)),
220 __engaged_(true) {}
221
222 template <class... _Args>
223 _LIBCPP_INLINE_VISIBILITY
224 constexpr
225 explicit __optional_storage(in_place_t, _Args&&... __args)
226 : __val_(_VSTD::forward<_Args>(__args)...),
227 __engaged_(true) {}
228};
229
230template <class _Tp>
231class __optional_storage<_Tp, true>
232{
233protected:
234 typedef _Tp value_type;
235 union
236 {
237 char __null_state_;
238 value_type __val_;
239 };
240 bool __engaged_ = false;
241
242 _LIBCPP_INLINE_VISIBILITY
243 constexpr __optional_storage() noexcept
244 : __null_state_('\0') {}
245
246 _LIBCPP_INLINE_VISIBILITY
247 __optional_storage(const __optional_storage& __x)
248 : __engaged_(__x.__engaged_)
249 {
250 if (__engaged_)
251 ::new(_VSTD::addressof(__val_)) value_type(__x.__val_);
252 }
253
254 _LIBCPP_INLINE_VISIBILITY
255 __optional_storage(__optional_storage&& __x)
256 noexcept(is_nothrow_move_constructible<value_type>::value)
257 : __engaged_(__x.__engaged_)
258 {
259 if (__engaged_)
260 ::new(_VSTD::addressof(__val_)) value_type(_VSTD::move(__x.__val_));
261 }
262
263 _LIBCPP_INLINE_VISIBILITY
264 constexpr __optional_storage(const value_type& __v)
265 : __val_(__v),
266 __engaged_(true) {}
267
268 _LIBCPP_INLINE_VISIBILITY
269 constexpr __optional_storage(value_type&& __v)
270 : __val_(_VSTD::move(__v)),
271 __engaged_(true) {}
272
273 template <class... _Args>
274 _LIBCPP_INLINE_VISIBILITY
275 constexpr
276 explicit __optional_storage(in_place_t, _Args&&... __args)
277 : __val_(_VSTD::forward<_Args>(__args)...),
278 __engaged_(true) {}
279};
280
281template <class _Tp>
282class optional
283 : private __optional_storage<_Tp>
284{
285 typedef __optional_storage<_Tp> __base;
286public:
287 typedef _Tp value_type;
288
289 static_assert(!is_reference<value_type>::value,
290 "Instantiation of optional with a reference type is ill-formed.");
291 static_assert(!is_same<typename remove_cv<value_type>::type, in_place_t>::value,
292 "Instantiation of optional with a in_place_t type is ill-formed.");
293 static_assert(!is_same<typename remove_cv<value_type>::type, nullopt_t>::value,
294 "Instantiation of optional with a nullopt_t type is ill-formed.");
295 static_assert(is_object<value_type>::value,
296 "Instantiation of optional with a non-object type is undefined behavior.");
297 static_assert(is_nothrow_destructible<value_type>::value,
298 "Instantiation of optional with an object type that is not noexcept destructible is undefined behavior.");
299
300 _LIBCPP_INLINE_VISIBILITY constexpr optional() noexcept {}
301 _LIBCPP_INLINE_VISIBILITY optional(const optional&) = default;
302 _LIBCPP_INLINE_VISIBILITY optional(optional&&) = default;
303 _LIBCPP_INLINE_VISIBILITY ~optional() = default;
304 _LIBCPP_INLINE_VISIBILITY constexpr optional(nullopt_t) noexcept {}
305 _LIBCPP_INLINE_VISIBILITY constexpr optional(const value_type& __v)
306 : __base(__v) {}
307 _LIBCPP_INLINE_VISIBILITY constexpr optional(value_type&& __v)
308 : __base(_VSTD::move(__v)) {}
309
310 template <class... _Args,
311 class = typename enable_if
312 <
313 is_constructible<value_type, _Args...>::value
314 >::type
315 >
316 _LIBCPP_INLINE_VISIBILITY
317 constexpr
318 explicit optional(in_place_t, _Args&&... __args)
319 : __base(in_place, _VSTD::forward<_Args>(__args)...) {}
320
321 template <class _Up, class... _Args,
322 class = typename enable_if
323 <
324 is_constructible<value_type, initializer_list<_Up>&, _Args...>::value
325 >::type
326 >
327 _LIBCPP_INLINE_VISIBILITY
328 constexpr
329 explicit optional(in_place_t, initializer_list<_Up> __il, _Args&&... __args)
330 : __base(in_place, __il, _VSTD::forward<_Args>(__args)...) {}
331
332 _LIBCPP_INLINE_VISIBILITY
333 optional& operator=(nullopt_t) noexcept
334 {
335 if (this->__engaged_)
336 {
337 this->__val_.~value_type();
338 this->__engaged_ = false;
339 }
340 return *this;
341 }
342
343 _LIBCPP_INLINE_VISIBILITY
344 optional&
345 operator=(const optional& __opt)
346 {
347 if (this->__engaged_ == __opt.__engaged_)
348 {
349 if (this->__engaged_)
350 this->__val_ = __opt.__val_;
351 }
352 else
353 {
354 if (this->__engaged_)
355 this->__val_.~value_type();
356 else
357 ::new(_VSTD::addressof(this->__val_)) value_type(__opt.__val_);
358 this->__engaged_ = __opt.__engaged_;
359 }
360 return *this;
361 }
362
363 _LIBCPP_INLINE_VISIBILITY
364 optional&
365 operator=(optional&& __opt)
366 noexcept(is_nothrow_move_assignable<value_type>::value &&
367 is_nothrow_move_constructible<value_type>::value)
368 {
369 if (this->__engaged_ == __opt.__engaged_)
370 {
371 if (this->__engaged_)
372 this->__val_ = _VSTD::move(__opt.__val_);
373 }
374 else
375 {
376 if (this->__engaged_)
377 this->__val_.~value_type();
378 else
379 ::new(_VSTD::addressof(this->__val_)) value_type(_VSTD::move(__opt.__val_));
380 this->__engaged_ = __opt.__engaged_;
381 }
382 return *this;
383 }
384
385 template <class _Up,
386 class = typename enable_if
387 <
388 is_same<typename remove_reference<_Up>::type, value_type>::value &&
389 is_constructible<value_type, _Up>::value &&
390 is_assignable<value_type&, _Up>::value
391 >::type
392 >
393 _LIBCPP_INLINE_VISIBILITY
394 optional&
395 operator=(_Up&& __v)
396 {
397 if (this->__engaged_)
398 this->__val_ = _VSTD::forward<_Up>(__v);
399 else
400 {
401 ::new(_VSTD::addressof(this->__val_)) value_type(_VSTD::forward<_Up>(__v));
402 this->__engaged_ = true;
403 }
404 return *this;
405 }
406
407 template <class... _Args,
408 class = typename enable_if
409 <
410 is_constructible<value_type, _Args...>::value
411 >::type
412 >
413 _LIBCPP_INLINE_VISIBILITY
414 void
415 emplace(_Args&&... __args)
416 {
417 *this = nullopt;
418 ::new(_VSTD::addressof(this->__val_)) value_type(_VSTD::forward<_Args>(__args)...);
419 this->__engaged_ = true;
420 }
421
422 template <class _Up, class... _Args,
423 class = typename enable_if
424 <
425 is_constructible<value_type, initializer_list<_Up>&, _Args...>::value
426 >::type
427 >
428 _LIBCPP_INLINE_VISIBILITY
429 void
430 emplace(initializer_list<_Up> __il, _Args&&... __args)
431 {
432 *this = nullopt;
433 ::new(_VSTD::addressof(this->__val_)) value_type(__il, _VSTD::forward<_Args>(__args)...);
434 this->__engaged_ = true;
435 }
436
437 _LIBCPP_INLINE_VISIBILITY
438 void
439 swap(optional& __opt)
440 noexcept(is_nothrow_move_constructible<value_type>::value &&
441 __is_nothrow_swappable<value_type>::value)
442 {
443 using _VSTD::swap;
444 if (this->__engaged_ == __opt.__engaged_)
445 {
446 if (this->__engaged_)
447 swap(this->__val_, __opt.__val_);
448 }
449 else
450 {
451 if (this->__engaged_)
452 {
453 ::new(_VSTD::addressof(__opt.__val_)) value_type(_VSTD::move(this->__val_));
454 this->__val_.~value_type();
455 }
456 else
457 {
458 ::new(_VSTD::addressof(this->__val_)) value_type(_VSTD::move(__opt.__val_));
459 __opt.__val_.~value_type();
460 }
461 swap(this->__engaged_, __opt.__engaged_);
462 }
463 }
464
465 _LIBCPP_INLINE_VISIBILITY
466 constexpr
467 value_type const*
468 operator->() const
469 {
470 _LIBCPP_ASSERT(this->__engaged_, "optional operator-> called for disengaged value");
471 return __operator_arrow(__has_operator_addressof<value_type>{});
472 }
473
474 _LIBCPP_INLINE_VISIBILITY
475 value_type*
476 operator->()
477 {
478 _LIBCPP_ASSERT(this->__engaged_, "optional operator-> called for disengaged value");
479 return _VSTD::addressof(this->__val_);
480 }
481
482 _LIBCPP_INLINE_VISIBILITY
483 constexpr
484 const value_type&
485 operator*() const
486 {
487 _LIBCPP_ASSERT(this->__engaged_, "optional operator* called for disengaged value");
488 return this->__val_;
489 }
490
491 _LIBCPP_INLINE_VISIBILITY
492 value_type&
493 operator*()
494 {
495 _LIBCPP_ASSERT(this->__engaged_, "optional operator* called for disengaged value");
496 return this->__val_;
497 }
498
499 _LIBCPP_INLINE_VISIBILITY
500 constexpr explicit operator bool() const noexcept {return this->__engaged_;}
501
502 _LIBCPP_INLINE_VISIBILITY
503 constexpr value_type const& value() const
504 {
505 if (!this->__engaged_)
506 throw bad_optional_access("optional<T>::value: not engaged");
507 return this->__val_;
508 }
509
510 _LIBCPP_INLINE_VISIBILITY
511 value_type& value()
512 {
513 if (!this->__engaged_)
514 throw bad_optional_access("optional<T>::value: not engaged");
515 return this->__val_;
516 }
517
518 template <class _Up>
519 _LIBCPP_INLINE_VISIBILITY
520 constexpr value_type value_or(_Up&& __v) const&
521 {
522 static_assert(is_copy_constructible<value_type>::value,
523 "optional<T>::value_or: T must be copy constructible");
524 static_assert(is_convertible<_Up, value_type>::value,
525 "optional<T>::value_or: U must be convertible to T");
526 return this->__engaged_ ? this->__val_ :
527 static_cast<value_type>(_VSTD::forward<_Up>(__v));
528 }
529
530 template <class _Up>
531 _LIBCPP_INLINE_VISIBILITY
532 value_type value_or(_Up&& __v) &&
533 {
534 static_assert(is_move_constructible<value_type>::value,
535 "optional<T>::value_or: T must be move constructible");
536 static_assert(is_convertible<_Up, value_type>::value,
537 "optional<T>::value_or: U must be convertible to T");
538 return this->__engaged_ ? _VSTD::move(this->__val_) :
539 static_cast<value_type>(_VSTD::forward<_Up>(__v));
540 }
541
542private:
543 _LIBCPP_INLINE_VISIBILITY
544 value_type const*
545 __operator_arrow(true_type) const
546 {
547 return _VSTD::addressof(this->__val_);
548 }
549
550 _LIBCPP_INLINE_VISIBILITY
551 constexpr
552 value_type const*
553 __operator_arrow(false_type) const
554 {
555 return &this->__val_;
556 }
557};
558
559template <class _Tp>
560inline _LIBCPP_INLINE_VISIBILITY
561constexpr
562bool
563operator==(const optional<_Tp>& __x, const optional<_Tp>& __y)
564{
565 if (static_cast<bool>(__x) != static_cast<bool>(__y))
566 return false;
567 if (!static_cast<bool>(__x))
568 return true;
569 return *__x == *__y;
570}
571
572template <class _Tp>
573inline _LIBCPP_INLINE_VISIBILITY
574constexpr
575bool
576operator<(const optional<_Tp>& __x, const optional<_Tp>& __y)
577{
578 if (!static_cast<bool>(__y))
579 return false;
580 if (!static_cast<bool>(__x))
581 return true;
582 return less<_Tp>{}(*__x, *__y);
583}
584
585template <class _Tp>
586inline _LIBCPP_INLINE_VISIBILITY
587constexpr
588bool
589operator==(const optional<_Tp>& __x, nullopt_t) noexcept
590{
591 return !static_cast<bool>(__x);
592}
593
594template <class _Tp>
595inline _LIBCPP_INLINE_VISIBILITY
596constexpr
597bool
598operator==(nullopt_t, const optional<_Tp>& __x) noexcept
599{
600 return !static_cast<bool>(__x);
601}
602
603template <class _Tp>
604inline _LIBCPP_INLINE_VISIBILITY
605constexpr
606bool
607operator<(const optional<_Tp>&, nullopt_t) noexcept
608{
609 return false;
610}
611
612template <class _Tp>
613inline _LIBCPP_INLINE_VISIBILITY
614constexpr
615bool
616operator<(nullopt_t, const optional<_Tp>& __x) noexcept
617{
618 return static_cast<bool>(__x);
619}
620
621template <class _Tp>
622inline _LIBCPP_INLINE_VISIBILITY
623constexpr
624bool
625operator==(const optional<_Tp>& __x, const _Tp& __v)
626{
627 return static_cast<bool>(__x) ? *__x == __v : false;
628}
629
630template <class _Tp>
631inline _LIBCPP_INLINE_VISIBILITY
632constexpr
633bool
634operator==(const _Tp& __v, const optional<_Tp>& __x)
635{
636 return static_cast<bool>(__x) ? *__x == __v : false;
637}
638
639template <class _Tp>
640inline _LIBCPP_INLINE_VISIBILITY
641constexpr
642bool
643operator<(const optional<_Tp>& __x, const _Tp& __v)
644{
645 return static_cast<bool>(__x) ? less<_Tp>{}(*__x, __v) : true;
646}
647
648template <class _Tp>
649inline _LIBCPP_INLINE_VISIBILITY
650constexpr
651bool
652operator<(const _Tp& __v, const optional<_Tp>& __x)
653{
654 return static_cast<bool>(__x) ? less<_Tp>{}(__v, *__x) : false;
655}
656
657template <class _Tp>
658inline _LIBCPP_INLINE_VISIBILITY
659void
660swap(optional<_Tp>& __x, optional<_Tp>& __y) noexcept(noexcept(__x.swap(__y)))
661{
662 __x.swap(__y);
663}
664
665template <class _Tp>
666inline _LIBCPP_INLINE_VISIBILITY
667constexpr
668optional<typename decay<_Tp>::type>
669make_optional(_Tp&& __v)
670{
671 return optional<typename decay<_Tp>::type>(_VSTD::forward<_Tp>(__v));
672}
673
Marshall Clow0cdbe602013-11-15 22:42:10 +0000674}}} // namespace std::experimental::__library_fundamentals_v1
675
676_LIBCPP_BEGIN_NAMESPACE_STD
677
Howard Hinnant01afa5c2013-09-02 20:30:37 +0000678template <class _Tp>
Marshall Clow0cdbe602013-11-15 22:42:10 +0000679struct _LIBCPP_TYPE_VIS_ONLY hash<std::experimental::optional<_Tp> >
Howard Hinnant01afa5c2013-09-02 20:30:37 +0000680{
Marshall Clow0cdbe602013-11-15 22:42:10 +0000681 typedef std::experimental::optional<_Tp> argument_type;
Howard Hinnant01afa5c2013-09-02 20:30:37 +0000682 typedef size_t result_type;
683
684 _LIBCPP_INLINE_VISIBILITY
685 result_type operator()(const argument_type& __opt) const _NOEXCEPT
686 {
687 return static_cast<bool>(__opt) ? hash<_Tp>()(*__opt) : 0;
688 }
689};
690
691_LIBCPP_END_NAMESPACE_STD
692
693#endif // _LIBCPP_STD_VER > 11
694
695#endif // _LIBCPP_ARRAY