1// Profile array implementation -*- C++ -*-
2
3// Copyright (C) 2012-2018 Free Software Foundation, Inc.
4//
5// This file is part of the GNU ISO C++ Library.  This library is free
6// software; you can redistribute it and/or modify it under the
7// terms of the GNU General Public License as published by the
8// Free Software Foundation; either version 3, or (at your option)
9// any later version.
10
11// This library is distributed in the hope that it will be useful,
12// but WITHOUT ANY WARRANTY; without even the implied warranty of
13// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14// GNU General Public License for more details.
15
16// Under Section 7 of GPL version 3, you are granted additional
17// permissions described in the GCC Runtime Library Exception, version
18// 3.1, as published by the Free Software Foundation.
19
20// You should have received a copy of the GNU General Public License and
21// a copy of the GCC Runtime Library Exception along with this program;
22// see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
23// <http://www.gnu.org/licenses/>.
24
25/** @file profile/array
26 *  This is a Standard C++ Library header.
27 */
28
29#ifndef _GLIBCXX_PROFILE_ARRAY
30#define _GLIBCXX_PROFILE_ARRAY 1
31
32#pragma GCC system_header
33
34#include <array>
35
36namespace std _GLIBCXX_VISIBILITY(default)
37{
38namespace __profile
39{
40  template<typename _Tp, std::size_t _Nm>
41    struct array
42    {
43      typedef _Tp 	    			      value_type;
44      typedef value_type*			      pointer;
45      typedef const value_type*                       const_pointer;
46      typedef value_type&                   	      reference;
47      typedef const value_type&             	      const_reference;
48      typedef value_type*                             iterator;
49      typedef const value_type*                       const_iterator;
50      typedef std::size_t                    	      size_type;
51      typedef std::ptrdiff_t                   	      difference_type;
52      typedef std::reverse_iterator<iterator>	      reverse_iterator;
53      typedef std::reverse_iterator<const_iterator>   const_reverse_iterator;
54
55      // Support for zero-sized arrays mandatory.
56      typedef _GLIBCXX_STD_C::__array_traits<_Tp, _Nm> _AT_Type;
57      typename _AT_Type::_Type                         _M_elems;
58
59      // No explicit construct/copy/destroy for aggregate type.
60
61      // DR 776.
62      void
63      fill(const value_type& __u)
64      { std::fill_n(begin(), size(), __u); }
65
66      void
67      swap(array& __other)
68      noexcept(_AT_Type::_Is_nothrow_swappable::value)
69      { std::swap_ranges(begin(), end(), __other.begin()); }
70
71      // Iterators.
72      _GLIBCXX17_CONSTEXPR iterator
73      begin() noexcept
74      { return iterator(data()); }
75
76      _GLIBCXX17_CONSTEXPR const_iterator
77      begin() const noexcept
78      { return const_iterator(data()); }
79
80      _GLIBCXX17_CONSTEXPR iterator
81      end() noexcept
82      { return iterator(data() + _Nm); }
83
84      _GLIBCXX17_CONSTEXPR const_iterator
85      end() const noexcept
86      { return const_iterator(data() + _Nm); }
87
88      _GLIBCXX17_CONSTEXPR reverse_iterator
89      rbegin() noexcept
90      { return reverse_iterator(end()); }
91
92      _GLIBCXX17_CONSTEXPR const_reverse_iterator
93      rbegin() const noexcept
94      { return const_reverse_iterator(end()); }
95
96      _GLIBCXX17_CONSTEXPR reverse_iterator
97      rend() noexcept
98      { return reverse_iterator(begin()); }
99
100      _GLIBCXX17_CONSTEXPR const_reverse_iterator
101      rend() const noexcept
102      { return const_reverse_iterator(begin()); }
103
104      _GLIBCXX17_CONSTEXPR const_iterator
105      cbegin() const noexcept
106      { return const_iterator(data()); }
107
108      _GLIBCXX17_CONSTEXPR const_iterator
109      cend() const noexcept
110      { return const_iterator(data() + _Nm); }
111
112      _GLIBCXX17_CONSTEXPR const_reverse_iterator
113      crbegin() const noexcept
114      { return const_reverse_iterator(end()); }
115
116      _GLIBCXX17_CONSTEXPR const_reverse_iterator
117      crend() const noexcept
118      { return const_reverse_iterator(begin()); }
119
120      // Capacity.
121      constexpr size_type
122      size() const noexcept { return _Nm; }
123
124      constexpr size_type
125      max_size() const noexcept { return _Nm; }
126
127      constexpr bool
128      empty() const noexcept { return size() == 0; }
129
130      // Element access.
131      reference
132      operator[](size_type __n) noexcept
133      {	return _AT_Type::_S_ref(_M_elems, __n); }
134
135      constexpr const_reference
136      operator[](size_type __n) const noexcept
137      { return _AT_Type::_S_ref(_M_elems, __n); }
138
139      _GLIBCXX17_CONSTEXPR reference
140      at(size_type __n)
141      {
142	if (__n >= _Nm)
143	  std::__throw_out_of_range_fmt(__N("array::at: __n "
144				            "(which is %zu) >= _Nm "
145					    "(which is %zu)"),
146					__n, _Nm);
147	return _AT_Type::_S_ref(_M_elems, __n);
148      }
149
150      constexpr const_reference
151      at(size_type __n) const
152      {
153	// Result of conditional expression must be an lvalue so use
154	// boolean ? lvalue : (throw-expr, lvalue)
155	return __n < _Nm ? _AT_Type::_S_ref(_M_elems, __n)
156	  : (std::__throw_out_of_range_fmt(__N("array::at: __n (which is %zu) "
157					       ">= _Nm (which is %zu)"),
158					   __n, _Nm),
159	     _AT_Type::_S_ref(_M_elems, 0));
160      }
161
162      _GLIBCXX17_CONSTEXPR reference
163      front() noexcept
164      { return *begin(); }
165
166      constexpr const_reference
167      front() const noexcept
168      { return _AT_Type::_S_ref(_M_elems, 0); }
169
170      _GLIBCXX17_CONSTEXPR reference
171      back() noexcept
172      { return _Nm ? *(end() - 1) : *end(); }
173
174      constexpr const_reference
175      back() const noexcept
176      {
177	return _Nm ? _AT_Type::_S_ref(_M_elems, _Nm - 1)
178		   : _AT_Type::_S_ref(_M_elems, 0);
179      }
180
181      _GLIBCXX17_CONSTEXPR pointer
182      data() noexcept
183      { return _AT_Type::_S_ptr(_M_elems); }
184
185      _GLIBCXX17_CONSTEXPR const_pointer
186      data() const noexcept
187      { return _AT_Type::_S_ptr(_M_elems); }
188    };
189
190  // Array comparisons.
191  template<typename _Tp, std::size_t _Nm>
192    inline bool
193    operator==(const array<_Tp, _Nm>& __one, const array<_Tp, _Nm>& __two)
194    { return std::equal(__one.begin(), __one.end(), __two.begin()); }
195
196  template<typename _Tp, std::size_t _Nm>
197    inline bool
198    operator!=(const array<_Tp, _Nm>& __one, const array<_Tp, _Nm>& __two)
199    { return !(__one == __two); }
200
201  template<typename _Tp, std::size_t _Nm>
202    inline bool
203    operator<(const array<_Tp, _Nm>& __a, const array<_Tp, _Nm>& __b)
204    {
205      return std::lexicographical_compare(__a.begin(), __a.end(),
206					  __b.begin(), __b.end());
207    }
208
209  template<typename _Tp, std::size_t _Nm>
210    inline bool
211    operator>(const array<_Tp, _Nm>& __one, const array<_Tp, _Nm>& __two)
212    { return __two < __one; }
213
214  template<typename _Tp, std::size_t _Nm>
215    inline bool
216    operator<=(const array<_Tp, _Nm>& __one, const array<_Tp, _Nm>& __two)
217    { return !(__one > __two); }
218
219  template<typename _Tp, std::size_t _Nm>
220    inline bool
221    operator>=(const array<_Tp, _Nm>& __one, const array<_Tp, _Nm>& __two)
222    { return !(__one < __two); }
223
224  // Specialized algorithms.
225  template<typename _Tp, std::size_t _Nm>
226    inline void
227    swap(array<_Tp, _Nm>& __one, array<_Tp, _Nm>& __two)
228    noexcept(noexcept(__one.swap(__two)))
229    { __one.swap(__two); }
230
231  template<std::size_t _Int, typename _Tp, std::size_t _Nm>
232    constexpr _Tp&
233    get(array<_Tp, _Nm>& __arr) noexcept
234    {
235      static_assert(_Int < _Nm, "index is out of bounds");
236      return _GLIBCXX_STD_C::__array_traits<_Tp, _Nm>::
237	_S_ref(__arr._M_elems, _Int);
238    }
239
240  template<std::size_t _Int, typename _Tp, std::size_t _Nm>
241    constexpr _Tp&&
242    get(array<_Tp, _Nm>&& __arr) noexcept
243    {
244      static_assert(_Int < _Nm, "index is out of bounds");
245      return std::move(__profile::get<_Int>(__arr));
246    }
247
248  template<std::size_t _Int, typename _Tp, std::size_t _Nm>
249    constexpr const _Tp&
250    get(const array<_Tp, _Nm>& __arr) noexcept
251    {
252      static_assert(_Int < _Nm, "index is out of bounds");
253      return _GLIBCXX_STD_C::__array_traits<_Tp, _Nm>::
254	_S_ref(__arr._M_elems, _Int);
255    }
256} // namespace __profile
257
258_GLIBCXX_BEGIN_NAMESPACE_VERSION
259  // Tuple interface to class template array.
260
261  /// tuple_size
262  template<typename _Tp, std::size_t _Nm>
263    struct tuple_size<std::__profile::array<_Tp, _Nm>>
264    : public integral_constant<std::size_t, _Nm> { };
265
266  /// tuple_element
267  template<std::size_t _Int, typename _Tp, std::size_t _Nm>
268    struct tuple_element<_Int, std::__profile::array<_Tp, _Nm>>
269    {
270      static_assert(_Int < _Nm, "index is out of bounds");
271      typedef _Tp type;
272    };
273
274  template<typename _Tp, std::size_t _Nm>
275    struct __is_tuple_like_impl<std::__profile::array<_Tp, _Nm>> : true_type
276    { };
277
278_GLIBCXX_END_NAMESPACE_VERSION
279} // namespace std
280
281#endif // _GLIBCXX_PROFILE_ARRAY
282