1 /* The following code declares class array, 2 * an STL container (as wrapper) for arrays of constant size. 3 * 4 * See 5 * http://www.josuttis.com/cppcode 6 * for details and the latest version. 7 * See 8 * http://www.boost.org/libs/array for Documentation. 9 * for documentation. 10 * 11 * (C) Copyright Nicolai M. Josuttis 2001. 12 * Permission to copy, use, modify, sell and distribute this software 13 * is granted provided this copyright notice appears in all copies. 14 * This software is provided "as is" without express or implied 15 * warranty, and with no claim as to its suitability for any purpose. 16 * 17 * 29 Jan 2004 - minor fixes (Nico Josuttis) 18 * 04 Dec 2003 - update to synch with library TR1 (Alisdair Meredith) 19 * 23 Aug 2002 - fix for Non-MSVC compilers combined with MSVC libraries. 20 * 05 Aug 2001 - minor update (Nico Josuttis) 21 * 20 Jan 2001 - STLport fix (Beman Dawes) 22 * 29 Sep 2000 - Initial Revision (Nico Josuttis) 23 * 24 * Jan 30, 2004 25 */ 26 // 27 // modifications: 28 // - in my namespace 29 // - removed boost includes 30 // - removed boost workarounds for broken compilers 31 // 32 #ifndef __UTIL_BOOST_ARRAY_HPP 33 #define __UTIL_BOOST_ARRAY_HPP 34 35 #include <cstddef> 36 #include <stdexcept> 37 #include <iterator> 38 #include <algorithm> 39 40 #include "debug.h" 41 42 namespace util { 43 44 template <typename T, std::size_t N> 45 class array { 46 public: 47 T elems[N]; // fixed-size array of elements of type T 48 49 public: 50 // type definitions 51 typedef T value_type; 52 typedef T* iterator; 53 typedef const T* const_iterator; 54 typedef T& reference; 55 typedef const T& const_reference; 56 typedef std::size_t size_type; 57 typedef std::ptrdiff_t difference_type; 58 59 // iterator support begin()60 iterator begin() { return elems; } begin()61 const_iterator begin() const { return elems; } end()62 iterator end() { return elems+N; } end()63 const_iterator end() const { return elems+N; } 64 65 // reverse iterator support 66 typedef std::reverse_iterator<iterator> reverse_iterator; 67 typedef std::reverse_iterator<const_iterator> const_reverse_iterator; 68 rbegin()69 reverse_iterator rbegin() { return reverse_iterator(end()); } rbegin()70 const_reverse_iterator rbegin() const { 71 return const_reverse_iterator(end()); 72 } rend()73 reverse_iterator rend() { return reverse_iterator(begin()); } rend()74 const_reverse_iterator rend() const { 75 return const_reverse_iterator(begin()); 76 } 77 78 // operator[] 79 reference operator[](size_type i) { return elems[i]; } 80 const_reference operator[](size_type i) const { return elems[i]; } 81 82 // at() with range check at(size_type i)83 reference at(size_type i) { rangecheck(i); return elems[i]; } at(size_type i)84 const_reference at(size_type i) const { rangecheck(i); return elems[i]; } 85 86 // front() and back() front()87 reference front() { return elems[0]; } front()88 const_reference front() const { return elems[0]; } back()89 reference back() { return elems[N-1]; } back()90 const_reference back() const { return elems[N-1]; } 91 92 // size is constant size()93 static size_type size() { return N; } empty()94 static bool empty() { return false; } max_size()95 static size_type max_size() { return N; } 96 enum { static_size = N }; 97 98 // swap (note: linear complexity in N, constant for given instantiation) swap(array<T,N> & y)99 void swap (array<T,N>& y) { 100 std::swap_ranges(begin(),end(),y.begin()); 101 } 102 103 // direct access to data (read-only) data()104 const T* data() const { return elems; } 105 106 // use array as C array (direct read/write access to data) data()107 T* data() { return elems; } 108 109 // assignment with type conversion 110 template <typename T2> 111 array<T,N>& operator= (const array<T2,N>& rhs) { 112 std::copy(rhs.begin(),rhs.end(), begin()); 113 return *this; 114 } 115 116 // assign one value to all elements assign(const T & value)117 void assign (const T& value) 118 { 119 std::fill_n(begin(),size(),value); 120 } 121 122 private: 123 // check range (may be private because it is static) rangecheck(size_type i)124 static void rangecheck (size_type i) { 125 if (i >= size()) { 126 throw std::out_of_range("array<>: index out of range"); 127 } 128 } 129 130 }; 131 132 // partial specialization for arrays of size 0 133 template <typename T> 134 class array<T,0> { 135 public: 136 char c; // to ensure different array intances return unique values for begin/end 137 138 public: 139 // type definitions 140 typedef T value_type; 141 typedef T* iterator; 142 typedef const T* const_iterator; 143 typedef T& reference; 144 typedef const T& const_reference; 145 typedef std::size_t size_type; 146 typedef std::ptrdiff_t difference_type; 147 148 // iterator support begin()149 iterator begin() { return reinterpret_cast< iterator >( &c ); } begin()150 const_iterator begin() const { return reinterpret_cast< const_iterator >( &c ); } end()151 iterator end() { return reinterpret_cast< iterator >( &c ); } end()152 const_iterator end() const { return reinterpret_cast< const_iterator >( &c ); } 153 154 // reverse iterator support 155 typedef std::reverse_iterator<iterator> reverse_iterator; 156 typedef std::reverse_iterator<const_iterator> const_reverse_iterator; 157 rbegin()158 reverse_iterator rbegin() { return reverse_iterator(end()); } rbegin()159 const_reverse_iterator rbegin() const { 160 return const_reverse_iterator(end()); 161 } rend()162 reverse_iterator rend() { return reverse_iterator(begin()); } rend()163 const_reverse_iterator rend() const { 164 return const_reverse_iterator(begin()); 165 } 166 167 // at() with range check at(size_type i)168 reference at(size_type i) { 169 throw std::out_of_range("array<0>: index out of range"); 170 } at(size_type i)171 const_reference at(size_type i) const { 172 throw std::out_of_range("<0>: index out of range"); 173 } 174 175 // size is constant size()176 static size_type size() { return 0; } empty()177 static bool empty() { return true; } max_size()178 static size_type max_size() { return 0; } 179 enum { static_size = 0 }; 180 181 // swap swap(array<T,0> & y)182 void swap (array<T,0>& y) { 183 // could swap value of c, but value is not part of documented array state 184 } 185 186 // direct access to data data()187 const T* data() const { return NULL; } data()188 T* data() { return NULL; } 189 190 // assignment with type conversion 191 template < typename T2 > 192 array< T,0 >& operator= (const array< T2, 0>& rhs) { 193 return *this; 194 } 195 196 // Calling these operations are undefined behaviour for 0-size arrays, 197 // but Library TR1 requires their presence. 198 // operator[] 199 reference operator[](size_type i) { makes_no_sense(); return *(T*) NULL; } 200 const_reference operator[](size_type i) const { makes_no_sense(); return *(T*) NULL; } 201 202 // front() and back() front()203 reference front() { makes_no_sense(); } front()204 const_reference front() const { makes_no_sense(); } back()205 reference back() { makes_no_sense(); } back()206 const_reference back() const { makes_no_sense(); } 207 208 private: 209 // helper for operations that have undefined behaviour for 0-size arrays, 210 // assert( false ); added to make lack of support clear makes_no_sense()211 static void makes_no_sense () { 212 assert(true); 213 throw std::out_of_range("array<0>: index out of range"); 214 } 215 }; 216 217 // comparisons 218 template<class T, std::size_t N> 219 bool operator== (const array<T,N>& x, const array<T,N>& y) { 220 return std::equal(x.begin(), x.end(), y.begin()); 221 } 222 template<class T, std::size_t N> 223 bool operator< (const array<T,N>& x, const array<T,N>& y) { 224 return std::lexicographical_compare(x.begin(),x.end(),y.begin(),y.end()); 225 } 226 template<class T, std::size_t N> 227 bool operator!= (const array<T,N>& x, const array<T,N>& y) { 228 return !(x==y); 229 } 230 template<class T, std::size_t N> 231 bool operator> (const array<T,N>& x, const array<T,N>& y) { 232 return y<x; 233 } 234 template<class T, std::size_t N> 235 bool operator<= (const array<T,N>& x, const array<T,N>& y) { 236 return !(y<x); 237 } 238 template<class T, std::size_t N> 239 bool operator>= (const array<T,N>& x, const array<T,N>& y) { 240 return !(x<y); 241 } 242 243 // global swap() 244 template<class T, std::size_t N> swap(array<T,N> & x,array<T,N> & y)245 inline void swap (array<T,N>& x, array<T,N>& y) { 246 x.swap(y); 247 } 248 249 } /* namespace util */ 250 251 #endif /*BOOST_ARRAY_HPP*/ 252