Array.h (3274B)
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */ 3 /* This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 /* A compile-time constant-length array with bounds-checking assertions. */ 8 9 #ifndef mozilla_Array_h 10 #define mozilla_Array_h 11 12 #include <cstddef> 13 14 #include <iterator> 15 #include <ostream> 16 #include <utility> 17 18 #include "mozilla/Assertions.h" 19 #include "mozilla/Attributes.h" 20 #include "mozilla/Likely.h" 21 22 namespace mozilla { 23 24 template <typename T, size_t _Length> 25 class MOZ_GSL_OWNER Array { 26 T mArr[_Length]; 27 28 public: 29 using ElementType = T; 30 static constexpr size_t Length = _Length; 31 32 constexpr Array() = default; 33 34 template <typename... Args> 35 MOZ_IMPLICIT constexpr Array(Args&&... aArgs) 36 : mArr{std::forward<Args>(aArgs)...} { 37 static_assert(sizeof...(aArgs) == Length, 38 "The number of arguments should be equal to the template " 39 "parameter Length"); 40 } 41 42 constexpr T& operator[](size_t aIndex) MOZ_LIFETIME_BOUND { 43 if (MOZ_UNLIKELY(aIndex >= Length)) { 44 detail::InvalidArrayIndex_CRASH(aIndex, Length); 45 } 46 return mArr[aIndex]; 47 } 48 49 constexpr const T& operator[](size_t aIndex) const MOZ_LIFETIME_BOUND { 50 if (MOZ_UNLIKELY(aIndex >= Length)) { 51 detail::InvalidArrayIndex_CRASH(aIndex, Length); 52 } 53 return mArr[aIndex]; 54 } 55 56 bool operator==(const Array<T, Length>& aOther) const { 57 for (size_t i = 0; i < Length; i++) { 58 if (mArr[i] != aOther[i]) { 59 return false; 60 } 61 } 62 return true; 63 } 64 65 typedef T* iterator; 66 typedef const T* const_iterator; 67 typedef std::reverse_iterator<T*> reverse_iterator; 68 typedef std::reverse_iterator<const T*> const_reverse_iterator; 69 70 // Methods for range-based for loops. 71 iterator begin() { return mArr; } 72 constexpr const_iterator begin() const { return mArr; } 73 constexpr const_iterator cbegin() const { return begin(); } 74 iterator end() { return mArr + Length; } 75 constexpr const_iterator end() const { return mArr + Length; } 76 constexpr const_iterator cend() const { return end(); } 77 78 // Method for std::size. 79 constexpr size_t size() const { return Length; } 80 81 // Methods for reverse iterating. 82 reverse_iterator rbegin() { return reverse_iterator(end()); } 83 const_reverse_iterator rbegin() const { 84 return const_reverse_iterator(end()); 85 } 86 const_reverse_iterator crbegin() const { return rbegin(); } 87 reverse_iterator rend() { return reverse_iterator(begin()); } 88 const_reverse_iterator rend() const { 89 return const_reverse_iterator(begin()); 90 } 91 const_reverse_iterator crend() const { return rend(); } 92 }; 93 94 template <typename T> 95 class Array<T, 0> { 96 public: 97 T& operator[](size_t aIndex) { MOZ_CRASH("indexing into zero-length array"); } 98 99 const T& operator[](size_t aIndex) const { 100 MOZ_CRASH("indexing into zero-length array"); 101 } 102 }; 103 104 // MOZ_DBG support 105 106 template <typename T, size_t Length> 107 std::ostream& operator<<(std::ostream& aOut, const Array<T, Length>& aArray) { 108 return aOut << Span(aArray); 109 } 110 111 } /* namespace mozilla */ 112 113 #endif /* mozilla_Array_h */