• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
21namespace std { namespace experimental {
22
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
112}}  // std::experimental
113
114*/
115
116#include <__config>
117#include <functional>
118#include <stdexcept>
119
120namespace std { namespace experimental {
121
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
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
164namespace std { namespace experimental { inline namespace __library_fundamentals_v1 {
165
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
678}}}  // namespace std::experimental::__library_fundamentals_v1
679
680_LIBCPP_BEGIN_NAMESPACE_STD
681
682template <class _Tp>
683struct _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
700