Nugget
array.h
1 // Copyright (c) Electronic Arts Inc. All rights reserved.
4 
5 
7 // Implements a templated array class as per the C++ standard TR1 (technical
8 // report 1, which is a list of proposed C++ library amendments).
9 // The primary distinctions between this array and TR1 array are:
10 // - array::size_type is defined as eastl_size_t instead of size_t in order
11 // to save memory and run faster on 64 bit systems.
13 
14 
15 #ifndef EASTL_ARRAY_H
16 #define EASTL_ARRAY_H
17 
18 
19 #include <EASTL/internal/config.h>
20 #include <EASTL/iterator.h>
21 #include <EASTL/algorithm.h>
22 #include <EASTL/utility.h>
23 #include <stddef.h>
24 
25 #if EASTL_EXCEPTIONS_ENABLED
26  EA_DISABLE_ALL_VC_WARNINGS()
27  #include <stdexcept> // std::out_of_range, std::length_error.
28  EA_RESTORE_ALL_VC_WARNINGS()
29 #endif
30 
31 #if defined(EA_PRAGMA_ONCE_SUPPORTED)
32  #pragma once // Some compilers (e.g. VC++) benefit significantly from using this. We've measured 3-4% build speed improvements in apps as a result.
33 #endif
34 
35 
36 
37 namespace eastl
38 {
39 
57  template <typename T, size_t N = 1>
58  struct array
59  {
60  public:
61  typedef array<T, N> this_type;
62  typedef T value_type;
63  typedef value_type& reference;
64  typedef const value_type& const_reference;
65  typedef value_type* iterator;
66  typedef const value_type* const_iterator;
69  typedef eastl_size_t size_type; // See config.h for the definition of eastl_size_t, which defaults to size_t.
70  typedef ptrdiff_t difference_type;
71 
72  public:
73  enum
74  {
75  count = N
76  };
77 
78  // Note that the member data is intentionally public.
79  // This allows for aggregate initialization of the
80  // object (e.g. array<int, 5> a = { 0, 3, 2, 4 }; )
81  value_type mValue[N ? N : 1];
82 
83  public:
84  // We intentionally provide no constructor, destructor, or assignment operator.
85 
86  void fill(const value_type& value);
87 
88  // Unlike the swap function for other containers, array::swap takes linear time,
89  // may exit via an exception, and does not cause iterators to become associated with the other container.
90  void swap(this_type& x) EA_NOEXCEPT_IF(eastl::is_nothrow_swappable<value_type>::value);
91 
92  EA_CPP14_CONSTEXPR iterator begin() EA_NOEXCEPT;
93  EA_CPP14_CONSTEXPR const_iterator begin() const EA_NOEXCEPT;
94  EA_CPP14_CONSTEXPR const_iterator cbegin() const EA_NOEXCEPT;
95 
96  EA_CPP14_CONSTEXPR iterator end() EA_NOEXCEPT;
97  EA_CPP14_CONSTEXPR const_iterator end() const EA_NOEXCEPT;
98  EA_CPP14_CONSTEXPR const_iterator cend() const EA_NOEXCEPT;
99 
100  EA_CPP14_CONSTEXPR reverse_iterator rbegin() EA_NOEXCEPT;
101  EA_CPP14_CONSTEXPR const_reverse_iterator rbegin() const EA_NOEXCEPT;
102  EA_CPP14_CONSTEXPR const_reverse_iterator crbegin() const EA_NOEXCEPT;
103 
104  EA_CPP14_CONSTEXPR reverse_iterator rend() EA_NOEXCEPT;
105  EA_CPP14_CONSTEXPR const_reverse_iterator rend() const EA_NOEXCEPT;
106  EA_CPP14_CONSTEXPR const_reverse_iterator crend() const EA_NOEXCEPT;
107 
108  EA_CPP14_CONSTEXPR bool empty() const EA_NOEXCEPT;
109  EA_CPP14_CONSTEXPR size_type size() const EA_NOEXCEPT;
110  EA_CPP14_CONSTEXPR size_type max_size() const EA_NOEXCEPT;
111 
112  EA_CPP14_CONSTEXPR T* data() EA_NOEXCEPT;
113  EA_CPP14_CONSTEXPR const T* data() const EA_NOEXCEPT;
114 
115  EA_CPP14_CONSTEXPR reference operator[](size_type i);
116  EA_CPP14_CONSTEXPR const_reference operator[](size_type i) const;
117  EA_CPP14_CONSTEXPR const_reference at(size_type i) const;
118  EA_CPP14_CONSTEXPR reference at(size_type i);
119 
120  EA_CPP14_CONSTEXPR reference front();
121  EA_CPP14_CONSTEXPR const_reference front() const;
122 
123  EA_CPP14_CONSTEXPR reference back();
124  EA_CPP14_CONSTEXPR const_reference back() const;
125 
126  bool validate() const;
127  int validate_iterator(const_iterator i) const;
128 
129  }; // class array
130 
131 
133  // template deduction guides
135  #ifdef __cpp_deduction_guides
136  template <class T, class... U> array(T, U...) -> array<T, 1 + sizeof...(U)>;
137  #endif
138 
139 
141  // array
143 
144 
145  template <typename T, size_t N>
146  inline void array<T, N>::fill(const value_type& value)
147  {
148  eastl::fill_n(&mValue[0], N, value);
149  }
150 
151 
152  template <typename T, size_t N>
153  inline void array<T, N>::swap(this_type& x) EA_NOEXCEPT_IF(eastl::is_nothrow_swappable<value_type>::value)
154  {
155  eastl::swap_ranges(&mValue[0], &mValue[N], &x.mValue[0]);
156  }
157 
158 
159  template <typename T, size_t N>
160  EA_CPP14_CONSTEXPR inline typename array<T, N>::iterator
161  array<T, N>::begin() EA_NOEXCEPT
162  {
163  return &mValue[0];
164  }
165 
166 
167  template <typename T, size_t N>
168  EA_CPP14_CONSTEXPR inline typename array<T, N>::const_iterator
169  array<T, N>::begin() const EA_NOEXCEPT
170  {
171  return &mValue[0];
172  }
173 
174 
175  template <typename T, size_t N>
176  EA_CPP14_CONSTEXPR inline typename array<T, N>::const_iterator
177  array<T, N>::cbegin() const EA_NOEXCEPT
178  {
179  return &mValue[0];
180  }
181 
182 
183  template <typename T, size_t N>
184  EA_CPP14_CONSTEXPR inline typename array<T, N>::iterator
185  array<T, N>::end() EA_NOEXCEPT
186  {
187  return &mValue[N];
188  }
189 
190 
191  template <typename T, size_t N>
192  EA_CPP14_CONSTEXPR inline typename array<T, N>::const_iterator
193  array<T, N>::end() const EA_NOEXCEPT
194  {
195  return &mValue[N];
196  }
197 
198 
199  template <typename T, size_t N>
200  EA_CPP14_CONSTEXPR inline typename array<T, N>::const_iterator
201  array<T, N>::cend() const EA_NOEXCEPT
202  {
203  return &mValue[N];
204  }
205 
206 
207  template <typename T, size_t N>
208  EA_CPP14_CONSTEXPR inline typename array<T, N>::reverse_iterator
209  array<T, N>::rbegin() EA_NOEXCEPT
210  {
211  return reverse_iterator(&mValue[N]);
212  }
213 
214 
215  template <typename T, size_t N>
216  EA_CPP14_CONSTEXPR inline typename array<T, N>::const_reverse_iterator
217  array<T, N>::rbegin() const EA_NOEXCEPT
218  {
219  return const_reverse_iterator(&mValue[N]);
220  }
221 
222 
223  template <typename T, size_t N>
224  EA_CPP14_CONSTEXPR inline typename array<T, N>::const_reverse_iterator
225  array<T, N>::crbegin() const EA_NOEXCEPT
226  {
227  return const_reverse_iterator(&mValue[N]);
228  }
229 
230 
231  template <typename T, size_t N>
232  EA_CPP14_CONSTEXPR inline typename array<T, N>::reverse_iterator
233  array<T, N>::rend() EA_NOEXCEPT
234  {
235  return reverse_iterator(&mValue[0]);
236  }
237 
238 
239  template <typename T, size_t N>
240  EA_CPP14_CONSTEXPR inline typename array<T, N>::const_reverse_iterator
241  array<T, N>::rend() const EA_NOEXCEPT
242  {
243  return const_reverse_iterator(static_cast<const_iterator>(&mValue[0]));
244  }
245 
246 
247  template <typename T, size_t N>
248  EA_CPP14_CONSTEXPR inline typename array<T, N>::const_reverse_iterator
249  array<T, N>::crend() const EA_NOEXCEPT
250  {
251  return const_reverse_iterator(static_cast<const_iterator>(&mValue[0]));
252  }
253 
254 
255  template <typename T, size_t N>
256  EA_CPP14_CONSTEXPR inline typename array<T, N>::size_type
257  array<T, N>::size() const EA_NOEXCEPT
258  {
259  return (size_type)N;
260  }
261 
262 
263  template <typename T, size_t N>
264  EA_CPP14_CONSTEXPR inline typename array<T, N>::size_type
265  array<T, N>::max_size() const EA_NOEXCEPT
266  {
267  return (size_type)N;
268  }
269 
270 
271  template <typename T, size_t N>
272  EA_CPP14_CONSTEXPR inline bool array<T, N>::empty() const EA_NOEXCEPT
273  {
274  return (N == 0);
275  }
276 
277 
278  template <typename T, size_t N>
279  EA_CPP14_CONSTEXPR inline typename array<T, N>::reference
280  array<T, N>::operator[](size_type i)
281  {
282  return mValue[i];
283  }
284 
285 
286  template <typename T, size_t N>
287  EA_CPP14_CONSTEXPR inline typename array<T, N>::const_reference
288  array<T, N>::operator[](size_type i) const
289  {
290  return mValue[i];
291  }
292 
293 
294  template <typename T, size_t N>
295  EA_CPP14_CONSTEXPR inline typename array<T, N>::reference
296  array<T, N>::front()
297  {
298  return mValue[0];
299  }
300 
301 
302  template <typename T, size_t N>
303  EA_CPP14_CONSTEXPR inline typename array<T, N>::const_reference
304  array<T, N>::front() const
305  {
306  return mValue[0];
307  }
308 
309 
310  template <typename T, size_t N>
311  EA_CPP14_CONSTEXPR inline typename array<T, N>::reference
312  array<T, N>::back()
313  {
314  return mValue[N - 1];
315  }
316 
317 
318  template <typename T, size_t N>
319  EA_CPP14_CONSTEXPR inline typename array<T, N>::const_reference
320  array<T, N>::back() const
321  {
322  return mValue[N - 1];
323  }
324 
325 
326  template <typename T, size_t N>
327  EA_CPP14_CONSTEXPR inline T* array<T, N>::data() EA_NOEXCEPT
328  {
329  return mValue;
330  }
331 
332 
333  template <typename T, size_t N>
334  EA_CPP14_CONSTEXPR inline const T* array<T, N>::data() const EA_NOEXCEPT
335  {
336  return mValue;
337  }
338 
339 
340  template <typename T, size_t N>
341  EA_CPP14_CONSTEXPR inline typename array<T, N>::const_reference array<T, N>::at(size_type i) const
342  {
343  #if EASTL_EXCEPTIONS_ENABLED
344  if(EASTL_UNLIKELY(i >= N))
345  throw std::out_of_range("array::at -- out of range");
346  #elif EASTL_ASSERT_ENABLED
347  if(EASTL_UNLIKELY(i >= N))
348  EASTL_FAIL_MSG("array::at -- out of range");
349  #endif
350 
351  return static_cast<const_reference>(mValue[i]);
352  }
353 
354 
355  template <typename T, size_t N>
356  EA_CPP14_CONSTEXPR inline typename array<T, N>::reference array<T, N>::at(size_type i)
357  {
358  #if EASTL_EXCEPTIONS_ENABLED
359  if(EASTL_UNLIKELY(i >= N))
360  throw std::out_of_range("array::at -- out of range");
361  #elif EASTL_ASSERT_ENABLED
362  if(EASTL_UNLIKELY(i >= N))
363  EASTL_FAIL_MSG("array::at -- out of range");
364  #endif
365 
366  return static_cast<reference>(mValue[i]);
367  }
368 
369 
370  template <typename T, size_t N>
371  inline bool array<T, N>::validate() const
372  {
373  return true; // There is nothing to do.
374  }
375 
376 
377  template <typename T, size_t N>
378  inline int array<T, N>::validate_iterator(const_iterator i) const
379  {
380  if(i >= mValue)
381  {
382  if(i < (mValue + N))
383  return (isf_valid | isf_current | isf_can_dereference);
384 
385  if(i <= (mValue + N))
386  return (isf_valid | isf_current);
387  }
388 
389  return isf_none;
390  }
391 
392 
393 
395  // global operators
397 
398  template <typename T, size_t N>
399  EA_CPP14_CONSTEXPR inline bool operator==(const array<T, N>& a, const array<T, N>& b)
400  {
401  return eastl::equal(&a.mValue[0], &a.mValue[N], &b.mValue[0]);
402  }
403 
404 
405  template <typename T, size_t N>
406  EA_CPP14_CONSTEXPR inline bool operator<(const array<T, N>& a, const array<T, N>& b)
407  {
408  return eastl::lexicographical_compare(&a.mValue[0], &a.mValue[N], &b.mValue[0], &b.mValue[N]);
409  }
410 
411 
412  template <typename T, size_t N>
413  EA_CPP14_CONSTEXPR inline bool operator!=(const array<T, N>& a, const array<T, N>& b)
414  {
415  return !eastl::equal(&a.mValue[0], &a.mValue[N], &b.mValue[0]);
416  }
417 
418 
419  template <typename T, size_t N>
420  EA_CPP14_CONSTEXPR inline bool operator>(const array<T, N>& a, const array<T, N>& b)
421  {
422  return eastl::lexicographical_compare(&b.mValue[0], &b.mValue[N], &a.mValue[0], &a.mValue[N]);
423  }
424 
425 
426  template <typename T, size_t N>
427  EA_CPP14_CONSTEXPR inline bool operator<=(const array<T, N>& a, const array<T, N>& b)
428  {
429  return !eastl::lexicographical_compare(&b.mValue[0], &b.mValue[N], &a.mValue[0], &a.mValue[N]);
430  }
431 
432 
433  template <typename T, size_t N>
434  EA_CPP14_CONSTEXPR inline bool operator>=(const array<T, N>& a, const array<T, N>& b)
435  {
436  return !eastl::lexicographical_compare(&a.mValue[0], &a.mValue[N], &b.mValue[0], &b.mValue[N]);
437  }
438 
439 
440  template <typename T, size_t N>
441  inline void swap(array<T, N>& a, array<T, N>& b)
442  {
443  eastl::swap_ranges(&a.mValue[0], &a.mValue[N], &b.mValue[0]);
444  }
445 
446 
448  // to_array
450  namespace internal
451  {
452  template<class T, size_t N, size_t... I>
453  EA_CONSTEXPR auto to_array(T (&a)[N], index_sequence<I...>)
454  {
455  return eastl::array<eastl::remove_cv_t<T>, N>{{a[I]...}};
456  }
457 
458  template<class T, size_t N, size_t... I>
459  EA_CONSTEXPR auto to_array(T (&&a)[N], index_sequence<I...>)
460  {
461  return eastl::array<eastl::remove_cv_t<T>, N>{{eastl::move(a[I])...}};
462  }
463  }
464 
465  template<class T, size_t N>
466  EA_CONSTEXPR eastl::array<eastl::remove_cv_t<T>, N> to_array(T (&a)[N])
467  {
468  static_assert(eastl::is_constructible_v<T, T&>, "element type T must be copy-initializable");
469  static_assert(!eastl::is_array_v<T>, "passing multidimensional arrays to to_array is ill-formed");
470  return internal::to_array(a, eastl::make_index_sequence<N>{});
471  }
472 
473  template<class T, size_t N>
474  EA_CONSTEXPR eastl::array<eastl::remove_cv_t<T>, N> to_array(T (&&a)[N])
475  {
476  static_assert(eastl::is_move_constructible_v<T>, "element type T must be move-constructible");
477  static_assert(!eastl::is_array_v<T>, "passing multidimensional arrays to to_array is ill-formed");
478  return internal::to_array(eastl::move(a), eastl::make_index_sequence<N>{});
479  }
480 
481 #if EASTL_TUPLE_ENABLED
482 
483  template <typename T, size_t N>
484  class tuple_size<array<T, N>> : public integral_constant<size_t, N>
485  {
486  };
487 
488  template <typename T, size_t N>
489  class tuple_size<const array<T, N>> : public integral_constant<size_t, N>
490  {
491  };
492 
493  template <size_t I, typename T, size_t N>
494  class tuple_element<I, array<T, N>>
495  {
496  public:
497  using type = T;
498  };
499 
500  template <size_t I, typename T, size_t N>
501  class tuple_element<I, const array<T, N>>
502  {
503  public:
504  using type = const T;
505  };
506 
507  template <size_t I>
508  struct GetArray
509  {
510  template <typename T, size_t N>
511  static EA_CONSTEXPR T& getInternal(array<T, N>& a)
512  {
513  return a[I];
514  }
515 
516  template <typename T, size_t N>
517  static EA_CONSTEXPR const T& getInternal(const array<T, N>& a)
518  {
519  return a[I];
520  }
521 
522  template <typename T, size_t N>
523  static EA_CONSTEXPR T&& getInternal(array<T, N>&& a)
524  {
525  return eastl::forward<T>(a[I]);
526  }
527  };
528 
529  template <size_t I, typename T, size_t N>
530  EA_CONSTEXPR tuple_element_t<I, array<T, N>>& get(array<T, N>& p)
531  {
532  return GetArray<I>::getInternal(p);
533  }
534 
535  template <size_t I, typename T, size_t N>
536  EA_CONSTEXPR const tuple_element_t<I, array<T, N>>& get(const array<T, N>& p)
537  {
538  return GetArray<I>::getInternal(p);
539  }
540 
541  template <size_t I, typename T, size_t N>
542  EA_CONSTEXPR tuple_element_t<I, array<T, N>>&& get(array<T, N>&& p)
543  {
544  return GetArray<I>::getInternal(eastl::move(p));
545  }
546 
547 #endif // EASTL_TUPLE_ENABLED
548 
549 
550 } // namespace eastl
551 
553 // C++17 structured binding support for eastl::array
554 //
555 #ifndef EA_COMPILER_NO_STRUCTURED_BINDING
556  #include <tuple>
557 
558  template <typename T, size_t N>
559  class std::tuple_size<::eastl::array<T, N>> : public ::eastl::integral_constant<size_t, N>
560  {
561  };
562 
563  template <size_t I, typename T, size_t N>
564  struct std::tuple_element<I, ::eastl::array<T, N>>
565  {
566  static_assert(I < N, "index is out of bounds");
567  using type = T;
568  };
569 #endif // EA_COMPILER_NO_STRUCTURED_BINDING
570 
571 
572 #endif // Header include guard
573 
574 
575 
576 
577 
578 
579 
580 
581 
582 
Definition: iterator.h:224
EA Standard Template Library.
Definition: algorithm.h:288
OutputIterator fill_n(OutputIterator first, Size n, const T &value)
Definition: fill_help.h:299
OutputIterator move(InputIterator first, InputIterator last, OutputIterator result)
Definition: copy_help.h:170
ForwardIterator2 swap_ranges(ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2)
Definition: utility.h:266
EA_CPP14_CONSTEXPR bool equal(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2)
Definition: algorithm.h:1856
bool lexicographical_compare(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2)
Definition: algorithm.h:1996
Definition: array.h:59
Definition: type_traits.h:263
Definition: utility.h:130