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