dynarray revision 261272
1261272Sdim// -*- C++ -*-
2261272Sdim//===-------------------------- dynarray ----------------------------------===//
3261272Sdim//
4261272Sdim//                     The LLVM Compiler Infrastructure
5261272Sdim//
6261272Sdim// This file is dual licensed under the MIT and the University of Illinois Open
7261272Sdim// Source Licenses. See LICENSE.TXT for details.
8261272Sdim//
9261272Sdim//===----------------------------------------------------------------------===//
10261272Sdim
11261272Sdim#ifndef _LIBCPP_DYNARRAY
12261272Sdim#define _LIBCPP_DYNARRAY
13261272Sdim
14261272Sdim#include <__config>
15261272Sdim#if _LIBCPP_STD_VER > 11
16261272Sdim
17261272Sdim/*
18261272Sdim    dynarray synopsis
19261272Sdim
20261272Sdimnamespace std { namespace experimental {
21261272Sdim
22261272Sdimtemplate< typename T >
23261272Sdimclass dynarray
24261272Sdim{
25261272Sdim    // types:
26261272Sdim    typedef       T                               value_type;
27261272Sdim    typedef       T&                              reference;
28261272Sdim    typedef const T&                              const_reference;
29261272Sdim    typedef       T*                              pointer;
30261272Sdim    typedef const T*                              const_pointer;
31261272Sdim    typedef       implementation-defined          iterator;
32261272Sdim    typedef       implementation-defined          const_iterator;
33261272Sdim    typedef reverse_iterator<iterator>            reverse_iterator;
34261272Sdim    typedef reverse_iterator<const_iterator>      const_reverse_iterator;
35261272Sdim    typedef size_t                                size_type;
36261272Sdim    typedef ptrdiff_t                             difference_type;
37261272Sdim
38261272Sdimpublic:
39261272Sdim    // construct/copy/destroy:
40261272Sdim    explicit dynarray(size_type c);
41261272Sdim    template <typename Alloc>
42261272Sdim      dynarray(size_type c, const Alloc& alloc);
43261272Sdim    dynarray(size_type c, const T& v);
44261272Sdim    template <typename Alloc>
45261272Sdim      dynarray(size_type c, const T& v, const Alloc& alloc);
46261272Sdim    dynarray(const dynarray& d);
47261272Sdim    template <typename Alloc>
48261272Sdim      dynarray(const dynarray& d, const Alloc& alloc);
49261272Sdim    dynarray(initializer_list<T>);
50261272Sdim    template <typename Alloc>
51261272Sdim      dynarray(initializer_list<T>, const Alloc& alloc);
52261272Sdim
53261272Sdim    dynarray& operator=(const dynarray&) = delete;
54261272Sdim    ~dynarray();
55261272Sdim
56261272Sdim    // iterators:
57261272Sdim    iterator       begin()        noexcept;
58261272Sdim    const_iterator begin()  const noexcept;
59261272Sdim    const_iterator cbegin() const noexcept;
60261272Sdim    iterator       end()          noexcept;
61261272Sdim    const_iterator end()    const noexcept;
62261272Sdim    const_iterator cend()   const noexcept;
63261272Sdim
64261272Sdim    reverse_iterator       rbegin()        noexcept;
65261272Sdim    const_reverse_iterator rbegin()  const noexcept;
66261272Sdim    const_reverse_iterator crbegin() const noexcept;
67261272Sdim    reverse_iterator       rend()          noexcept;
68261272Sdim    const_reverse_iterator rend()    const noexcept;
69261272Sdim    const_reverse_iterator crend()   const noexcept;
70261272Sdim
71261272Sdim    // capacity:
72261272Sdim    size_type size()     const noexcept;
73261272Sdim    size_type max_size() const noexcept;
74261272Sdim    bool      empty()    const noexcept;
75261272Sdim
76261272Sdim    // element access:
77261272Sdim    reference       operator[](size_type n);
78261272Sdim    const_reference operator[](size_type n) const;
79261272Sdim
80261272Sdim    reference       front();
81261272Sdim    const_reference front() const;
82261272Sdim    reference       back();
83261272Sdim    const_reference back()  const;
84261272Sdim
85261272Sdim    const_reference at(size_type n) const;
86261272Sdim    reference       at(size_type n);
87261272Sdim
88261272Sdim    // data access:
89261272Sdim    T*       data()       noexcept;
90261272Sdim    const T* data() const noexcept;
91261272Sdim
92261272Sdim    // mutating member functions:
93261272Sdim    void fill(const T& v);
94261272Sdim};
95261272Sdim
96261272Sdim}}  // std::experimental
97261272Sdim
98261272Sdim*/
99261272Sdim
100261272Sdim#include <__functional_base>
101261272Sdim#include <iterator>
102261272Sdim#include <stdexcept>
103261272Sdim#include <initializer_list>
104261272Sdim#include <new>
105261272Sdim#include <algorithm>
106261272Sdim
107261272Sdim#if defined(_LIBCPP_NO_EXCEPTIONS)
108261272Sdim    #include <cassert>
109261272Sdim#endif
110261272Sdim
111261272Sdim#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
112261272Sdim#pragma GCC system_header
113261272Sdim#endif
114261272Sdim
115261272Sdimnamespace std { namespace experimental { inline namespace __array_extensions_v1 {
116261272Sdim
117261272Sdimtemplate <class _Tp>
118261272Sdimstruct _LIBCPP_TYPE_VIS_ONLY dynarray
119261272Sdim{
120261272Sdimpublic:
121261272Sdim    // types:
122261272Sdim    typedef dynarray __self;
123261272Sdim    typedef _Tp                                   value_type;
124261272Sdim    typedef value_type&                           reference;
125261272Sdim    typedef const value_type&                     const_reference;
126261272Sdim    typedef value_type*                           iterator;
127261272Sdim    typedef const value_type*                     const_iterator;
128261272Sdim    typedef value_type*                           pointer;
129261272Sdim    typedef const value_type*                     const_pointer;
130261272Sdim    typedef size_t                                size_type;
131261272Sdim    typedef ptrdiff_t                             difference_type;
132261272Sdim    typedef std::reverse_iterator<iterator>       reverse_iterator;
133261272Sdim    typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
134261272Sdim
135261272Sdimprivate:
136261272Sdim    size_t                  __size_;
137261272Sdim    value_type *            __base_;
138261272Sdim    _LIBCPP_ALWAYS_INLINE dynarray () noexcept : __base_(nullptr), __size_(0) {}
139261272Sdim    
140261272Sdim    static inline _LIBCPP_INLINE_VISIBILITY value_type* __allocate ( size_t count )
141261272Sdim    {
142261272Sdim        if ( numeric_limits<size_t>::max() / sizeof (value_type) <= count )
143261272Sdim        {
144261272Sdim#ifndef _LIBCPP_NO_EXCEPTIONS
145261272Sdim            throw bad_array_length();
146261272Sdim#else
147261272Sdim            assert(!"dynarray::allocation");
148261272Sdim#endif
149261272Sdim        }
150261272Sdim        return static_cast<value_type *> (::operator new (sizeof(value_type) * count));
151261272Sdim    }
152261272Sdim
153261272Sdim    static inline _LIBCPP_INLINE_VISIBILITY void __deallocate ( value_type* __ptr ) noexcept
154261272Sdim    {
155261272Sdim        ::operator delete (static_cast<void *> (__ptr));
156261272Sdim    }
157261272Sdim
158261272Sdimpublic:
159261272Sdim
160261272Sdim    explicit dynarray(size_type __c);
161261272Sdim    dynarray(size_type __c, const value_type& __v);
162261272Sdim    dynarray(const dynarray& __d);
163261272Sdim    dynarray(initializer_list<value_type>);
164261272Sdim
165261272Sdim//  We're not implementing these right now.
166261272Sdim//  Waiting for the resolution of LWG issue #2235
167261272Sdim//     template <typename _Alloc>
168261272Sdim//       dynarray(size_type __c, const _Alloc& __alloc);
169261272Sdim//     template <typename _Alloc>
170261272Sdim//       dynarray(size_type __c, const value_type& __v, const _Alloc& __alloc);
171261272Sdim//     template <typename _Alloc>
172261272Sdim//       dynarray(const dynarray& __d, const _Alloc& __alloc);
173261272Sdim//     template <typename _Alloc>
174261272Sdim//       dynarray(initializer_list<value_type>, const _Alloc& __alloc);
175261272Sdim
176261272Sdim    dynarray& operator=(const dynarray&) = delete;
177261272Sdim    ~dynarray();
178261272Sdim
179261272Sdim    // iterators:
180261272Sdim    inline _LIBCPP_INLINE_VISIBILITY iterator       begin()        noexcept { return iterator(data()); }
181261272Sdim    inline _LIBCPP_INLINE_VISIBILITY const_iterator begin()  const noexcept { return const_iterator(data()); }
182261272Sdim    inline _LIBCPP_INLINE_VISIBILITY const_iterator cbegin() const noexcept { return const_iterator(data()); }
183261272Sdim    inline _LIBCPP_INLINE_VISIBILITY iterator       end()          noexcept { return iterator(data() + __size_); }
184261272Sdim    inline _LIBCPP_INLINE_VISIBILITY const_iterator end()    const noexcept { return const_iterator(data() + __size_); }
185261272Sdim    inline _LIBCPP_INLINE_VISIBILITY const_iterator cend()   const noexcept { return const_iterator(data() + __size_); }
186261272Sdim
187261272Sdim    inline _LIBCPP_INLINE_VISIBILITY reverse_iterator       rbegin()        noexcept { return reverse_iterator(end()); }
188261272Sdim    inline _LIBCPP_INLINE_VISIBILITY const_reverse_iterator rbegin()  const noexcept { return const_reverse_iterator(end()); }
189261272Sdim    inline _LIBCPP_INLINE_VISIBILITY const_reverse_iterator crbegin() const noexcept { return const_reverse_iterator(end()); }
190261272Sdim    inline _LIBCPP_INLINE_VISIBILITY reverse_iterator       rend()          noexcept { return reverse_iterator(begin()); }
191261272Sdim    inline _LIBCPP_INLINE_VISIBILITY const_reverse_iterator rend()    const noexcept { return const_reverse_iterator(begin()); }
192261272Sdim    inline _LIBCPP_INLINE_VISIBILITY const_reverse_iterator crend()   const noexcept { return const_reverse_iterator(begin()); }
193261272Sdim
194261272Sdim    // capacity:
195261272Sdim    inline _LIBCPP_INLINE_VISIBILITY size_type size()     const noexcept { return __size_; }
196261272Sdim    inline _LIBCPP_INLINE_VISIBILITY size_type max_size() const noexcept { return __size_; }
197261272Sdim    inline _LIBCPP_INLINE_VISIBILITY bool      empty()    const noexcept { return __size_ == 0; }
198261272Sdim
199261272Sdim    // element access:
200261272Sdim    inline _LIBCPP_INLINE_VISIBILITY reference       operator[](size_type __n)       { return data()[__n]; }
201261272Sdim    inline _LIBCPP_INLINE_VISIBILITY const_reference operator[](size_type __n) const { return data()[__n]; }
202261272Sdim
203261272Sdim    inline _LIBCPP_INLINE_VISIBILITY reference       front()       { return data()[0]; }
204261272Sdim    inline _LIBCPP_INLINE_VISIBILITY const_reference front() const { return data()[0]; }
205261272Sdim    inline _LIBCPP_INLINE_VISIBILITY reference       back()        { return data()[__size_-1]; }
206261272Sdim    inline _LIBCPP_INLINE_VISIBILITY const_reference back()  const { return data()[__size_-1]; }
207261272Sdim
208261272Sdim    inline _LIBCPP_INLINE_VISIBILITY const_reference at(size_type __n) const;
209261272Sdim    inline _LIBCPP_INLINE_VISIBILITY reference       at(size_type __n);
210261272Sdim
211261272Sdim    // data access:
212261272Sdim    inline _LIBCPP_INLINE_VISIBILITY _Tp*       data()       noexcept { return __base_; }
213261272Sdim    inline _LIBCPP_INLINE_VISIBILITY const _Tp* data() const noexcept { return __base_; }
214261272Sdim
215261272Sdim    // mutating member functions:
216261272Sdim    inline _LIBCPP_INLINE_VISIBILITY void fill(const value_type& __v) { fill_n(begin(), __size_, __v); }
217261272Sdim};
218261272Sdim
219261272Sdimtemplate <class _Tp>
220261272Sdiminline _LIBCPP_INLINE_VISIBILITY
221261272Sdimdynarray<_Tp>::dynarray(size_type __c) : dynarray ()
222261272Sdim{
223261272Sdim    __base_ = __allocate (__c);
224261272Sdim    value_type *__data = data ();
225261272Sdim    for ( __size_ = 0; __size_ < __c; ++__size_, ++__data )
226261272Sdim        ::new (__data) value_type;
227261272Sdim}
228261272Sdim
229261272Sdimtemplate <class _Tp>
230261272Sdiminline _LIBCPP_INLINE_VISIBILITY
231261272Sdimdynarray<_Tp>::dynarray(size_type __c, const value_type& __v) : dynarray ()
232261272Sdim{
233261272Sdim    __base_ = __allocate (__c);
234261272Sdim    value_type *__data = data ();
235261272Sdim    for ( __size_ = 0; __size_ < __c; ++__size_, ++__data )
236261272Sdim        ::new (__data) value_type (__v);
237261272Sdim}
238261272Sdim
239261272Sdimtemplate <class _Tp>
240261272Sdiminline _LIBCPP_INLINE_VISIBILITY
241261272Sdimdynarray<_Tp>::dynarray(initializer_list<value_type> __il) : dynarray ()
242261272Sdim{
243261272Sdim    size_t sz = __il.size();
244261272Sdim    __base_ = __allocate (sz);
245261272Sdim    value_type *__data = data ();
246261272Sdim    auto src = __il.begin();
247261272Sdim    for ( __size_ = 0; __size_ < sz; ++__size_, ++__data, ++src )
248261272Sdim        ::new (__data) value_type (*src);
249261272Sdim}
250261272Sdim
251261272Sdimtemplate <class _Tp>
252261272Sdiminline _LIBCPP_INLINE_VISIBILITY
253261272Sdimdynarray<_Tp>::dynarray(const dynarray& __d) : dynarray ()
254261272Sdim{
255261272Sdim    size_t sz = __d.size();
256261272Sdim    __base_ = __allocate (sz);
257261272Sdim    value_type *__data = data ();
258261272Sdim    auto src = __d.begin();
259261272Sdim    for ( __size_ = 0; __size_ < sz; ++__size_, ++__data, ++src )
260261272Sdim        ::new (__data) value_type (*src);
261261272Sdim}
262261272Sdim
263261272Sdimtemplate <class _Tp>
264261272Sdiminline _LIBCPP_INLINE_VISIBILITY
265261272Sdimdynarray<_Tp>::~dynarray()
266261272Sdim{ 
267261272Sdim    value_type *__data = data () + __size_;
268261272Sdim    for ( size_t i = 0; i < __size_; ++i )
269261272Sdim        (--__data)->value_type::~value_type();
270261272Sdim    __deallocate ( __base_ );
271261272Sdim}
272261272Sdim
273261272Sdimtemplate <class _Tp>
274261272Sdiminline _LIBCPP_INLINE_VISIBILITY
275261272Sdimtypename dynarray<_Tp>::reference
276261272Sdimdynarray<_Tp>::at(size_type __n)
277261272Sdim{
278261272Sdim    if (__n >= __size_)
279261272Sdim    {
280261272Sdim#ifndef _LIBCPP_NO_EXCEPTIONS
281261272Sdim        throw out_of_range("dynarray::at");
282261272Sdim#else
283261272Sdim        assert(!"dynarray::at out_of_range");
284261272Sdim#endif
285261272Sdim    }
286261272Sdim    return data()[__n];
287261272Sdim}
288261272Sdim
289261272Sdimtemplate <class _Tp>
290261272Sdiminline _LIBCPP_INLINE_VISIBILITY
291261272Sdimtypename dynarray<_Tp>::const_reference
292261272Sdimdynarray<_Tp>::at(size_type __n) const
293261272Sdim{
294261272Sdim    if (__n >= __size_)
295261272Sdim    {
296261272Sdim#ifndef _LIBCPP_NO_EXCEPTIONS
297261272Sdim        throw out_of_range("dynarray::at");
298261272Sdim#else
299261272Sdim        assert(!"dynarray::at out_of_range");
300261272Sdim#endif
301261272Sdim    }
302261272Sdim    return data()[__n];
303261272Sdim}
304261272Sdim
305261272Sdim}}}
306261272Sdim
307261272Sdim
308261272Sdim_LIBCPP_BEGIN_NAMESPACE_STD
309261272Sdimtemplate <class _Tp, class _Alloc>
310261272Sdimstruct _LIBCPP_TYPE_VIS_ONLY uses_allocator<std::experimental::dynarray<_Tp>, _Alloc> : true_type {};
311261272Sdim_LIBCPP_END_NAMESPACE_STD
312261272Sdim
313261272Sdim#endif  // if _LIBCPP_STD_VER > 11 
314261272Sdim#endif  // _LIBCPP_DYNARRAY
315