1139790Simp// -*- C++ -*-
297261Sjake//===---------------------------- array -----------------------------------===//
397261Sjake//
497261Sjake//                     The LLVM Compiler Infrastructure
597261Sjake//
697261Sjake// This file is dual licensed under the MIT and the University of Illinois Open
797261Sjake// Source Licenses. See LICENSE.TXT for details.
897261Sjake//
997261Sjake//===----------------------------------------------------------------------===//
1097261Sjake
1197261Sjake#ifndef _LIBCPP_ARRAY
1297261Sjake#define _LIBCPP_ARRAY
1397261Sjake
1497261Sjake/*
1597261Sjake    array synopsis
1697261Sjake
1797261Sjakenamespace std
1897261Sjake{
1997261Sjaketemplate <class T, size_t N >
2097261Sjakestruct array
2197261Sjake{
2297261Sjake    // types:
2397261Sjake    typedef T & reference;
2497261Sjake    typedef const T & const_reference;
2597261Sjake    typedef implementation defined iterator;
2697261Sjake    typedef implementation defined const_iterator;
2797261Sjake    typedef size_t size_type;
2897261Sjake    typedef ptrdiff_t difference_type;
2997261Sjake    typedef T value_type;
3097261Sjake    typedef T* pointer;
3197261Sjake    typedef const T* const_pointer;
3297261Sjake    typedef std::reverse_iterator<iterator> reverse_iterator;
3397261Sjake    typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
3497261Sjake
3597261Sjake    // No explicit construct/copy/destroy for aggregate type
3697261Sjake    void fill(const T& u);
3797261Sjake    void swap(array& a) noexcept(noexcept(swap(declval<T&>(), declval<T&>())));
3897261Sjake
39123418Speter    // iterators:
4097261Sjake    iterator begin() noexcept;
4197261Sjake    const_iterator begin() const noexcept;
4297261Sjake    iterator end() noexcept;
4397261Sjake    const_iterator end() const noexcept;
44208283Smarcel
4597261Sjake    reverse_iterator rbegin() noexcept;
46208283Smarcel    const_reverse_iterator rbegin() const noexcept;
47208283Smarcel    reverse_iterator rend() noexcept;
4897261Sjake    const_reverse_iterator rend() const noexcept;
49208283Smarcel
5097261Sjake    const_iterator cbegin() const noexcept;
51123418Speter    const_iterator cend() const noexcept;
52123418Speter    const_reverse_iterator crbegin() const noexcept;
53123418Speter    const_reverse_iterator crend() const noexcept;
54123418Speter
55123418Speter    // capacity:
56123418Speter    constexpr size_type size() const noexcept;
57123418Speter    constexpr size_type max_size() const noexcept;
58123418Speter    constexpr bool empty() const noexcept;
59123418Speter
60123418Speter    // element access:
6197261Sjake    reference operator[](size_type n);
62123420Speter    const_reference operator[](size_type n) const; // constexpr in C++14
6397261Sjake    const_reference at(size_type n) const; // constexpr in C++14
6497261Sjake    reference at(size_type n);
6597261Sjake
66    reference front();
67    const_reference front() const; // constexpr in C++14
68    reference back();
69    const_reference back() const; // constexpr in C++14
70
71    T* data() noexcept;
72    const T* data() const noexcept;
73};
74
75template <class T, size_t N>
76  bool operator==(const array<T,N>& x, const array<T,N>& y);
77template <class T, size_t N>
78  bool operator!=(const array<T,N>& x, const array<T,N>& y);
79template <class T, size_t N>
80  bool operator<(const array<T,N>& x, const array<T,N>& y);
81template <class T, size_t N>
82  bool operator>(const array<T,N>& x, const array<T,N>& y);
83template <class T, size_t N>
84  bool operator<=(const array<T,N>& x, const array<T,N>& y);
85template <class T, size_t N>
86  bool operator>=(const array<T,N>& x, const array<T,N>& y);
87
88template <class T, size_t N >
89  void swap(array<T,N>& x, array<T,N>& y) noexcept(noexcept(x.swap(y)));
90
91template <class T> class tuple_size;
92template <size_t I, class T> class tuple_element;
93template <class T, size_t N> struct tuple_size<array<T, N>>;
94template <size_t I, class T, size_t N> struct tuple_element<I, array<T, N>>;
95template <size_t I, class T, size_t N> T& get(array<T, N>&) noexcept; // constexpr in C++14
96template <size_t I, class T, size_t N> const T& get(const array<T, N>&) noexcept; // constexpr in C++14
97template <size_t I, class T, size_t N> T&& get(array<T, N>&&) noexcept; // constexpr in C++14
98template <size_t I, class T, size_t N> const T&& get(const array<T, N>&&) noexcept; // constexpr in C++14
99
100}  // std
101
102*/
103
104#include <__config>
105#include <__tuple>
106#include <type_traits>
107#include <utility>
108#include <iterator>
109#include <algorithm>
110#include <stdexcept>
111#if defined(_LIBCPP_NO_EXCEPTIONS)
112    #include <cassert>
113#endif
114
115#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
116#pragma GCC system_header
117#endif
118
119_LIBCPP_BEGIN_NAMESPACE_STD
120
121template <class _Tp, size_t _Size>
122struct _LIBCPP_TYPE_VIS_ONLY array
123{
124    // types:
125    typedef array __self;
126    typedef _Tp                                   value_type;
127    typedef value_type&                           reference;
128    typedef const value_type&                     const_reference;
129    typedef value_type*                           iterator;
130    typedef const value_type*                     const_iterator;
131    typedef value_type*                           pointer;
132    typedef const value_type*                     const_pointer;
133    typedef size_t                                size_type;
134    typedef ptrdiff_t                             difference_type;
135    typedef std::reverse_iterator<iterator>       reverse_iterator;
136    typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
137
138    value_type __elems_[_Size > 0 ? _Size : 1];
139
140    // No explicit construct/copy/destroy for aggregate type
141    _LIBCPP_INLINE_VISIBILITY void fill(const value_type& __u)
142        {_VSTD::fill_n(__elems_, _Size, __u);}
143    _LIBCPP_INLINE_VISIBILITY
144    void swap(array& __a) _NOEXCEPT_(__is_nothrow_swappable<_Tp>::value)
145        {_VSTD::swap_ranges(__elems_, __elems_ + _Size, __a.__elems_);}
146
147    // iterators:
148    _LIBCPP_INLINE_VISIBILITY
149    iterator begin() _NOEXCEPT {return iterator(__elems_);}
150    _LIBCPP_INLINE_VISIBILITY
151    const_iterator begin() const _NOEXCEPT {return const_iterator(__elems_);}
152    _LIBCPP_INLINE_VISIBILITY
153    iterator end() _NOEXCEPT {return iterator(__elems_ + _Size);}
154    _LIBCPP_INLINE_VISIBILITY
155    const_iterator end() const _NOEXCEPT {return const_iterator(__elems_ + _Size);}
156
157    _LIBCPP_INLINE_VISIBILITY
158    reverse_iterator rbegin() _NOEXCEPT {return reverse_iterator(end());}
159    _LIBCPP_INLINE_VISIBILITY
160    const_reverse_iterator rbegin() const _NOEXCEPT {return const_reverse_iterator(end());}
161    _LIBCPP_INLINE_VISIBILITY
162    reverse_iterator rend() _NOEXCEPT {return reverse_iterator(begin());}
163    _LIBCPP_INLINE_VISIBILITY
164    const_reverse_iterator rend() const _NOEXCEPT {return const_reverse_iterator(begin());}
165
166    _LIBCPP_INLINE_VISIBILITY
167    const_iterator cbegin() const _NOEXCEPT {return begin();}
168    _LIBCPP_INLINE_VISIBILITY
169    const_iterator cend() const _NOEXCEPT {return end();}
170    _LIBCPP_INLINE_VISIBILITY
171    const_reverse_iterator crbegin() const _NOEXCEPT {return rbegin();}
172    _LIBCPP_INLINE_VISIBILITY
173    const_reverse_iterator crend() const _NOEXCEPT {return rend();}
174
175    // capacity:
176    _LIBCPP_INLINE_VISIBILITY
177    _LIBCPP_CONSTEXPR size_type size() const _NOEXCEPT {return _Size;}
178    _LIBCPP_INLINE_VISIBILITY
179    _LIBCPP_CONSTEXPR size_type max_size() const _NOEXCEPT {return _Size;}
180    _LIBCPP_INLINE_VISIBILITY
181    _LIBCPP_CONSTEXPR bool empty() const _NOEXCEPT {return _Size == 0;}
182
183    // element access:
184    _LIBCPP_INLINE_VISIBILITY reference operator[](size_type __n)             {return __elems_[__n];}
185    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 const_reference operator[](size_type __n) const {return __elems_[__n];}
186    reference at(size_type __n);
187    _LIBCPP_CONSTEXPR_AFTER_CXX11 const_reference at(size_type __n) const;
188
189    _LIBCPP_INLINE_VISIBILITY reference front()             {return __elems_[0];}
190    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 const_reference front() const {return __elems_[0];}
191    _LIBCPP_INLINE_VISIBILITY reference back()              {return __elems_[_Size > 0 ? _Size-1 : 0];}
192    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 const_reference back() const  {return __elems_[_Size > 0 ? _Size-1 : 0];}
193
194    _LIBCPP_INLINE_VISIBILITY
195    value_type* data() _NOEXCEPT {return __elems_;}
196    _LIBCPP_INLINE_VISIBILITY
197    const value_type* data() const _NOEXCEPT {return __elems_;}
198};
199
200template <class _Tp, size_t _Size>
201typename array<_Tp, _Size>::reference
202array<_Tp, _Size>::at(size_type __n)
203{
204    if (__n >= _Size)
205#ifndef _LIBCPP_NO_EXCEPTIONS
206        throw out_of_range("array::at");
207#else
208        assert(!"array::at out_of_range");
209#endif
210    return __elems_[__n];
211}
212
213template <class _Tp, size_t _Size>
214_LIBCPP_CONSTEXPR_AFTER_CXX11
215typename array<_Tp, _Size>::const_reference
216array<_Tp, _Size>::at(size_type __n) const
217{
218    if (__n >= _Size)
219#ifndef _LIBCPP_NO_EXCEPTIONS
220        throw out_of_range("array::at");
221#else
222        assert(!"array::at out_of_range");
223#endif
224    return __elems_[__n];
225}
226
227template <class _Tp, size_t _Size>
228inline _LIBCPP_INLINE_VISIBILITY
229bool
230operator==(const array<_Tp, _Size>& __x, const array<_Tp, _Size>& __y)
231{
232    return _VSTD::equal(__x.__elems_, __x.__elems_ + _Size, __y.__elems_);
233}
234
235template <class _Tp, size_t _Size>
236inline _LIBCPP_INLINE_VISIBILITY
237bool
238operator!=(const array<_Tp, _Size>& __x, const array<_Tp, _Size>& __y)
239{
240    return !(__x == __y);
241}
242
243template <class _Tp, size_t _Size>
244inline _LIBCPP_INLINE_VISIBILITY
245bool
246operator<(const array<_Tp, _Size>& __x, const array<_Tp, _Size>& __y)
247{
248    return _VSTD::lexicographical_compare(__x.__elems_, __x.__elems_ + _Size, __y.__elems_, __y.__elems_ + _Size);
249}
250
251template <class _Tp, size_t _Size>
252inline _LIBCPP_INLINE_VISIBILITY
253bool
254operator>(const array<_Tp, _Size>& __x, const array<_Tp, _Size>& __y)
255{
256    return __y < __x;
257}
258
259template <class _Tp, size_t _Size>
260inline _LIBCPP_INLINE_VISIBILITY
261bool
262operator<=(const array<_Tp, _Size>& __x, const array<_Tp, _Size>& __y)
263{
264    return !(__y < __x);
265}
266
267template <class _Tp, size_t _Size>
268inline _LIBCPP_INLINE_VISIBILITY
269bool
270operator>=(const array<_Tp, _Size>& __x, const array<_Tp, _Size>& __y)
271{
272    return !(__x < __y);
273}
274
275template <class _Tp, size_t _Size>
276inline _LIBCPP_INLINE_VISIBILITY
277typename enable_if
278<
279    __is_swappable<_Tp>::value,
280    void
281>::type
282swap(const array<_Tp, _Size>& __x, const array<_Tp, _Size>& __y)
283                                  _NOEXCEPT_(__is_nothrow_swappable<_Tp>::value)
284{
285    __x.swap(__y);
286}
287
288template <class _Tp, size_t _Size>
289class _LIBCPP_TYPE_VIS_ONLY tuple_size<array<_Tp, _Size> >
290    : public integral_constant<size_t, _Size> {};
291
292template <size_t _Ip, class _Tp, size_t _Size>
293class _LIBCPP_TYPE_VIS_ONLY tuple_element<_Ip, array<_Tp, _Size> >
294{
295public:
296    typedef _Tp type;
297};
298
299template <size_t _Ip, class _Tp, size_t _Size>
300inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11
301_Tp&
302get(array<_Tp, _Size>& __a) _NOEXCEPT
303{
304    static_assert(_Ip < _Size, "Index out of bounds in std::get<> (std::array)");
305    return __a.__elems_[_Ip];
306}
307
308template <size_t _Ip, class _Tp, size_t _Size>
309inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11
310const _Tp&
311get(const array<_Tp, _Size>& __a) _NOEXCEPT
312{
313    static_assert(_Ip < _Size, "Index out of bounds in std::get<> (const std::array)");
314    return __a.__elems_[_Ip];
315}
316
317#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
318
319template <size_t _Ip, class _Tp, size_t _Size>
320inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11
321_Tp&&
322get(array<_Tp, _Size>&& __a) _NOEXCEPT
323{
324    static_assert(_Ip < _Size, "Index out of bounds in std::get<> (std::array &&)");
325    return _VSTD::move(__a.__elems_[_Ip]);
326}
327
328template <size_t _Ip, class _Tp, size_t _Size>
329inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11
330const _Tp&&
331get(const array<_Tp, _Size>&& __a) _NOEXCEPT
332{
333    static_assert(_Ip < _Size, "Index out of bounds in std::get<> (const std::array &&)");
334    return _VSTD::move(__a.__elems_[_Ip]);
335}
336
337#endif  // _LIBCPP_HAS_NO_RVALUE_REFERENCES
338
339_LIBCPP_END_NAMESPACE_STD
340
341#endif  // _LIBCPP_ARRAY
342