]> CyberLeo.Net >> Repos - FreeBSD/stable/9.git/blob - contrib/libc++/include/experimental/optional
MFC r261283:
[FreeBSD/stable/9.git] / contrib / libc++ / include / experimental / optional
1 // -*- 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
21 namespace std { namespace experimental {
22
23 // optional for object types
24 template <class T>
25 class optional
26 {
27 public:
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
72 struct in_place_t{};
73 constexpr in_place_t in_place{};
74
75 // Disengaged state indicator
76 struct nullopt_t{see below};
77 constexpr nullopt_t nullopt(unspecified);
78
79 // class bad_optional_access
80 class bad_optional_access
81     : public logic_error
82 {
83 public:
84     explicit bad_optional_access(const string& what_arg);
85     explicit bad_optional_access(const char* what_arg);
86 };
87
88 // Relational operators
89 template <class T> constexpr bool operator==(const optional<T>&, const optional<T>&);
90 template <class T> constexpr bool operator< (const optional<T>&, const optional<T>&);
91
92 // Comparison with nullopt
93 template <class T> constexpr bool operator==(const optional<T>&, nullopt_t) noexcept;
94 template <class T> constexpr bool operator==(nullopt_t, const optional<T>&) noexcept;
95 template <class T> constexpr bool operator<(const optional<T>&, nullopt_t) noexcept;
96 template <class T> constexpr bool operator<(nullopt_t, const optional<T>&) noexcept;
97
98 // Comparison with T
99 template <class T> constexpr bool operator==(const optional<T>&, const T&);
100 template <class T> constexpr bool operator==(const T&, const optional<T>&);
101 template <class T> constexpr bool operator<(const optional<T>&, const T&);
102 template <class T> constexpr bool operator<(const T&, const optional<T>&);
103
104 // Specialized algorithms
105 template <class T> void swap(optional<T>&, optional<T>&) noexcept(see below);
106 template <class T> constexpr optional<typename decay<T>::type> make_optional(T&&);
107
108 // hash support
109 template <class T> struct hash;
110 template <class T> struct hash<optional<T>>;
111
112 }}  // std::experimental
113
114 */
115
116 #include <__config>
117 #include <functional>
118 #include <stdexcept>
119
120 namespace std { namespace experimental {
121
122 class _LIBCPP_EXCEPTION_ABI bad_optional_access
123     : public logic_error
124 {
125 public:
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
134 private:
135     bad_optional_access(const bad_optional_access&);
136     bad_optional_access& operator=(const bad_optional_access&);
137 public:
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
143 }}  // std::experimental
144
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
164 namespace std { namespace experimental { inline namespace __library_fundamentals_v1 {
165
166 struct in_place_t {};
167 constexpr in_place_t in_place{};
168
169 struct nullopt_t
170 {
171     explicit constexpr nullopt_t(int) noexcept {}
172 };
173
174 constexpr nullopt_t nullopt{0};
175
176 template <class _Tp, bool = is_trivially_destructible<_Tp>::value>
177 class __optional_storage
178 {
179 protected:
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
234 template <class _Tp>
235 class __optional_storage<_Tp, true>
236 {
237 protected:
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
285 template <class _Tp>
286 class optional
287     : private __optional_storage<_Tp>
288 {
289     typedef __optional_storage<_Tp> __base;
290 public:
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
546 private:
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
563 template <class _Tp>
564 inline _LIBCPP_INLINE_VISIBILITY
565 constexpr
566 bool
567 operator==(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
576 template <class _Tp>
577 inline _LIBCPP_INLINE_VISIBILITY
578 constexpr
579 bool
580 operator<(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
589 template <class _Tp>
590 inline _LIBCPP_INLINE_VISIBILITY
591 constexpr
592 bool
593 operator==(const optional<_Tp>& __x, nullopt_t) noexcept
594 {
595     return !static_cast<bool>(__x);
596 }
597
598 template <class _Tp>
599 inline _LIBCPP_INLINE_VISIBILITY
600 constexpr
601 bool
602 operator==(nullopt_t, const optional<_Tp>& __x) noexcept
603 {
604     return !static_cast<bool>(__x);
605 }
606
607 template <class _Tp>
608 inline _LIBCPP_INLINE_VISIBILITY
609 constexpr
610 bool
611 operator<(const optional<_Tp>&, nullopt_t) noexcept
612 {
613     return false;
614 }
615
616 template <class _Tp>
617 inline _LIBCPP_INLINE_VISIBILITY
618 constexpr
619 bool
620 operator<(nullopt_t, const optional<_Tp>& __x) noexcept
621 {
622     return static_cast<bool>(__x);
623 }
624
625 template <class _Tp>
626 inline _LIBCPP_INLINE_VISIBILITY
627 constexpr
628 bool
629 operator==(const optional<_Tp>& __x, const _Tp& __v)
630 {
631     return static_cast<bool>(__x) ? *__x == __v : false;
632 }
633
634 template <class _Tp>
635 inline _LIBCPP_INLINE_VISIBILITY
636 constexpr
637 bool
638 operator==(const _Tp& __v, const optional<_Tp>& __x)
639 {
640     return static_cast<bool>(__x) ? *__x == __v : false;
641 }
642
643 template <class _Tp>
644 inline _LIBCPP_INLINE_VISIBILITY
645 constexpr
646 bool
647 operator<(const optional<_Tp>& __x, const _Tp& __v)
648 {
649     return static_cast<bool>(__x) ? less<_Tp>{}(*__x, __v) : true;
650 }
651
652 template <class _Tp>
653 inline _LIBCPP_INLINE_VISIBILITY
654 constexpr
655 bool
656 operator<(const _Tp& __v, const optional<_Tp>& __x)
657 {
658     return static_cast<bool>(__x) ? less<_Tp>{}(__v, *__x) : false;
659 }
660
661 template <class _Tp>
662 inline _LIBCPP_INLINE_VISIBILITY
663 void
664 swap(optional<_Tp>& __x, optional<_Tp>& __y) noexcept(noexcept(__x.swap(__y)))
665 {
666     __x.swap(__y);
667 }
668
669 template <class _Tp>
670 inline _LIBCPP_INLINE_VISIBILITY
671 constexpr
672 optional<typename decay<_Tp>::type>
673 make_optional(_Tp&& __v)
674 {
675     return optional<typename decay<_Tp>::type>(_VSTD::forward<_Tp>(__v));
676 }
677
678 }}}  // namespace std::experimental::__library_fundamentals_v1
679
680 _LIBCPP_BEGIN_NAMESPACE_STD
681
682 template <class _Tp>
683 struct _LIBCPP_TYPE_VIS_ONLY hash<std::experimental::optional<_Tp> >
684 {
685     typedef std::experimental::optional<_Tp> argument_type;
686     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