1 # /* ************************************************************************** |
1 /* The following code declares class array, |
2 # * * |
2 * an STL container (as wrapper) for arrays of constant size. |
3 # * (C) Copyright Paul Mensonides 2002. |
3 * |
4 # * Distributed under the Boost Software License, Version 1.0. (See |
4 * See |
5 # * accompanying file LICENSE_1_0.txt or copy at |
5 * http://www.boost.org/libs/array/ |
6 # * http://www.boost.org/LICENSE_1_0.txt) |
6 * for documentation. |
7 # * * |
7 * |
8 # ************************************************************************** */ |
8 * The original author site is at: http://www.josuttis.com/ |
9 # |
9 * |
10 # /* See http://www.boost.org for most recent version. */ |
10 * (C) Copyright Nicolai M. Josuttis 2001. |
11 # |
11 * |
12 # ifndef BOOST_PREPROCESSOR_ARRAY_HPP |
12 * Distributed under the Boost Software License, Version 1.0. (See |
13 # define BOOST_PREPROCESSOR_ARRAY_HPP |
13 * accompanying file LICENSE_1_0.txt or copy at |
14 # |
14 * http://www.boost.org/LICENSE_1_0.txt) |
15 # include <boost/preprocessor/array/data.hpp> |
15 * |
16 # include <boost/preprocessor/array/elem.hpp> |
16 * 29 Jan 2004 - c_array() added, BOOST_NO_PRIVATE_IN_AGGREGATE removed (Nico Josuttis) |
17 # include <boost/preprocessor/array/insert.hpp> |
17 * 23 Aug 2002 - fix for Non-MSVC compilers combined with MSVC libraries. |
18 # include <boost/preprocessor/array/pop_back.hpp> |
18 * 05 Aug 2001 - minor update (Nico Josuttis) |
19 # include <boost/preprocessor/array/pop_front.hpp> |
19 * 20 Jan 2001 - STLport fix (Beman Dawes) |
20 # include <boost/preprocessor/array/push_back.hpp> |
20 * 29 Sep 2000 - Initial Revision (Nico Josuttis) |
21 # include <boost/preprocessor/array/push_front.hpp> |
21 * |
22 # include <boost/preprocessor/array/remove.hpp> |
22 * Jan 29, 2004 |
23 # include <boost/preprocessor/array/replace.hpp> |
23 */ |
24 # include <boost/preprocessor/array/reverse.hpp> |
24 #ifndef BOOST_ARRAY_HPP |
25 # include <boost/preprocessor/array/size.hpp> |
25 #define BOOST_ARRAY_HPP |
26 # |
26 |
27 # endif |
27 #include <cstddef> |
|
28 #include <stdexcept> |
|
29 #include <boost/assert.hpp> |
|
30 |
|
31 // Handles broken standard libraries better than <iterator> |
|
32 #include <boost/detail/iterator.hpp> |
|
33 #include <boost/throw_exception.hpp> |
|
34 #include <algorithm> |
|
35 |
|
36 // FIXES for broken compilers |
|
37 #include <boost/config.hpp> |
|
38 |
|
39 |
|
40 namespace boost { |
|
41 |
|
42 template<class T, std::size_t N> |
|
43 class array { |
|
44 public: |
|
45 T elems[N]; // fixed-size array of elements of type T |
|
46 |
|
47 public: |
|
48 // type definitions |
|
49 typedef T value_type; |
|
50 typedef T* iterator; |
|
51 typedef const T* const_iterator; |
|
52 typedef T& reference; |
|
53 typedef const T& const_reference; |
|
54 typedef std::size_t size_type; |
|
55 typedef std::ptrdiff_t difference_type; |
|
56 |
|
57 // iterator support |
|
58 iterator begin() { return elems; } |
|
59 const_iterator begin() const { return elems; } |
|
60 iterator end() { return elems+N; } |
|
61 const_iterator end() const { return elems+N; } |
|
62 |
|
63 // reverse iterator support |
|
64 #if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) && !defined(BOOST_MSVC_STD_ITERATOR) && !defined(BOOST_NO_STD_ITERATOR_TRAITS) |
|
65 typedef std::reverse_iterator<iterator> reverse_iterator; |
|
66 typedef std::reverse_iterator<const_iterator> const_reverse_iterator; |
|
67 #elif defined(_MSC_VER) && (_MSC_VER == 1300) && defined(BOOST_DINKUMWARE_STDLIB) && (BOOST_DINKUMWARE_STDLIB == 310) |
|
68 // workaround for broken reverse_iterator in VC7 |
|
69 typedef std::reverse_iterator<std::_Ptrit<value_type, difference_type, iterator, |
|
70 reference, iterator, reference> > reverse_iterator; |
|
71 typedef std::reverse_iterator<std::_Ptrit<value_type, difference_type, const_iterator, |
|
72 const_reference, iterator, reference> > const_reverse_iterator; |
|
73 #else |
|
74 // workaround for broken reverse_iterator implementations |
|
75 typedef std::reverse_iterator<iterator,T> reverse_iterator; |
|
76 typedef std::reverse_iterator<const_iterator,T> const_reverse_iterator; |
|
77 #endif |
|
78 |
|
79 reverse_iterator rbegin() { return reverse_iterator(end()); } |
|
80 const_reverse_iterator rbegin() const { |
|
81 return const_reverse_iterator(end()); |
|
82 } |
|
83 reverse_iterator rend() { return reverse_iterator(begin()); } |
|
84 const_reverse_iterator rend() const { |
|
85 return const_reverse_iterator(begin()); |
|
86 } |
|
87 |
|
88 // operator[] |
|
89 reference operator[](size_type i) |
|
90 { |
|
91 BOOST_ASSERT( i < N && "out of range" ); |
|
92 return elems[i]; |
|
93 } |
|
94 |
|
95 const_reference operator[](size_type i) const |
|
96 { |
|
97 BOOST_ASSERT( i < N && "out of range" ); |
|
98 return elems[i]; |
|
99 } |
|
100 |
|
101 // at() with range check |
|
102 reference at(size_type i) { rangecheck(i); return elems[i]; } |
|
103 const_reference at(size_type i) const { rangecheck(i); return elems[i]; } |
|
104 |
|
105 // front() and back() |
|
106 reference front() |
|
107 { |
|
108 return elems[0]; |
|
109 } |
|
110 |
|
111 const_reference front() const |
|
112 { |
|
113 return elems[0]; |
|
114 } |
|
115 |
|
116 reference back() |
|
117 { |
|
118 return elems[N-1]; |
|
119 } |
|
120 |
|
121 const_reference back() const |
|
122 { |
|
123 return elems[N-1]; |
|
124 } |
|
125 |
|
126 // size is constant |
|
127 static size_type size() { return N; } |
|
128 static bool empty() { return false; } |
|
129 static size_type max_size() { return N; } |
|
130 enum { static_size = N }; |
|
131 |
|
132 // swap (note: linear complexity) |
|
133 void swap (array<T,N>& y) { |
|
134 std::swap_ranges(begin(),end(),y.begin()); |
|
135 } |
|
136 |
|
137 // direct access to data (read-only) |
|
138 const T* data() const { return elems; } |
|
139 T* data() { return elems; } |
|
140 |
|
141 // use array as C array (direct read/write access to data) |
|
142 T* c_array() { return elems; } |
|
143 |
|
144 // assignment with type conversion |
|
145 template <typename T2> |
|
146 array<T,N>& operator= (const array<T2,N>& rhs) { |
|
147 std::copy(rhs.begin(),rhs.end(), begin()); |
|
148 return *this; |
|
149 } |
|
150 |
|
151 // assign one value to all elements |
|
152 void assign (const T& value) |
|
153 { |
|
154 std::fill_n(begin(),size(),value); |
|
155 } |
|
156 |
|
157 // check range (may be private because it is static) |
|
158 static void rangecheck (size_type i) { |
|
159 if (i >= size()) { |
|
160 throw std::range_error("array<>: index out of range"); |
|
161 } |
|
162 } |
|
163 |
|
164 }; |
|
165 |
|
166 #if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) |
|
167 template< class T > |
|
168 class array< T, 0 > { |
|
169 |
|
170 public: |
|
171 // type definitions |
|
172 typedef T value_type; |
|
173 typedef T* iterator; |
|
174 typedef const T* const_iterator; |
|
175 typedef T& reference; |
|
176 typedef const T& const_reference; |
|
177 typedef std::size_t size_type; |
|
178 typedef std::ptrdiff_t difference_type; |
|
179 |
|
180 // iterator support |
|
181 iterator begin() { return iterator( reinterpret_cast< T * >( this ) ); } |
|
182 const_iterator begin() const { return const_iterator( reinterpret_cast< const T * >( this ) ); } |
|
183 iterator end() { return begin(); } |
|
184 const_iterator end() const { return begin(); } |
|
185 |
|
186 // reverse iterator support |
|
187 #if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) && !defined(BOOST_MSVC_STD_ITERATOR) && !defined(BOOST_NO_STD_ITERATOR_TRAITS) |
|
188 typedef std::reverse_iterator<iterator> reverse_iterator; |
|
189 typedef std::reverse_iterator<const_iterator> const_reverse_iterator; |
|
190 #elif defined(_MSC_VER) && (_MSC_VER == 1300) && defined(BOOST_DINKUMWARE_STDLIB) && (BOOST_DINKUMWARE_STDLIB == 310) |
|
191 // workaround for broken reverse_iterator in VC7 |
|
192 typedef std::reverse_iterator<std::_Ptrit<value_type, difference_type, iterator, |
|
193 reference, iterator, reference> > reverse_iterator; |
|
194 typedef std::reverse_iterator<std::_Ptrit<value_type, difference_type, const_iterator, |
|
195 const_reference, iterator, reference> > const_reverse_iterator; |
|
196 #else |
|
197 // workaround for broken reverse_iterator implementations |
|
198 typedef std::reverse_iterator<iterator,T> reverse_iterator; |
|
199 typedef std::reverse_iterator<const_iterator,T> const_reverse_iterator; |
|
200 #endif |
|
201 |
|
202 reverse_iterator rbegin() { return reverse_iterator(end()); } |
|
203 const_reverse_iterator rbegin() const { |
|
204 return const_reverse_iterator(end()); |
|
205 } |
|
206 reverse_iterator rend() { return reverse_iterator(begin()); } |
|
207 const_reverse_iterator rend() const { |
|
208 return const_reverse_iterator(begin()); |
|
209 } |
|
210 |
|
211 // operator[] |
|
212 reference operator[](size_type i) |
|
213 { |
|
214 return failed_rangecheck(); |
|
215 } |
|
216 |
|
217 const_reference operator[](size_type i) const |
|
218 { |
|
219 return failed_rangecheck(); |
|
220 } |
|
221 |
|
222 // at() with range check |
|
223 reference at(size_type i) { return failed_rangecheck(); } |
|
224 const_reference at(size_type i) const { return failed_rangecheck(); } |
|
225 |
|
226 // front() and back() |
|
227 reference front() |
|
228 { |
|
229 return failed_rangecheck(); |
|
230 } |
|
231 |
|
232 const_reference front() const |
|
233 { |
|
234 return failed_rangecheck(); |
|
235 } |
|
236 |
|
237 reference back() |
|
238 { |
|
239 return failed_rangecheck(); |
|
240 } |
|
241 |
|
242 const_reference back() const |
|
243 { |
|
244 return failed_rangecheck(); |
|
245 } |
|
246 |
|
247 // size is constant |
|
248 static size_type size() { return 0; } |
|
249 static bool empty() { return true; } |
|
250 static size_type max_size() { return 0; } |
|
251 enum { static_size = 0 }; |
|
252 |
|
253 void swap (array<T,0>& y) { |
|
254 } |
|
255 |
|
256 // direct access to data (read-only) |
|
257 const T* data() const { return 0; } |
|
258 T* data() { return 0; } |
|
259 |
|
260 // use array as C array (direct read/write access to data) |
|
261 T* c_array() { return 0; } |
|
262 |
|
263 // assignment with type conversion |
|
264 template <typename T2> |
|
265 array<T,0>& operator= (const array<T2,0>& ) { |
|
266 return *this; |
|
267 } |
|
268 |
|
269 // assign one value to all elements |
|
270 void assign (const T& ) { } |
|
271 |
|
272 // check range (may be private because it is static) |
|
273 static reference failed_rangecheck () { |
|
274 std::range_error e("attempt to access element of an empty array"); |
|
275 boost::throw_exception(e); |
|
276 // |
|
277 // We need to return something here to keep |
|
278 // some compilers happy: however we will never |
|
279 // actually get here.... |
|
280 // |
|
281 static T placeholder; |
|
282 return placeholder; |
|
283 } |
|
284 }; |
|
285 #endif |
|
286 |
|
287 // comparisons |
|
288 template<class T, std::size_t N> |
|
289 bool operator== (const array<T,N>& x, const array<T,N>& y) { |
|
290 return std::equal(x.begin(), x.end(), y.begin()); |
|
291 } |
|
292 template<class T, std::size_t N> |
|
293 bool operator< (const array<T,N>& x, const array<T,N>& y) { |
|
294 return std::lexicographical_compare(x.begin(),x.end(),y.begin(),y.end()); |
|
295 } |
|
296 template<class T, std::size_t N> |
|
297 bool operator!= (const array<T,N>& x, const array<T,N>& y) { |
|
298 return !(x==y); |
|
299 } |
|
300 template<class T, std::size_t N> |
|
301 bool operator> (const array<T,N>& x, const array<T,N>& y) { |
|
302 return y<x; |
|
303 } |
|
304 template<class T, std::size_t N> |
|
305 bool operator<= (const array<T,N>& x, const array<T,N>& y) { |
|
306 return !(y<x); |
|
307 } |
|
308 template<class T, std::size_t N> |
|
309 bool operator>= (const array<T,N>& x, const array<T,N>& y) { |
|
310 return !(x<y); |
|
311 } |
|
312 |
|
313 // global swap() |
|
314 template<class T, std::size_t N> |
|
315 inline void swap (array<T,N>& x, array<T,N>& y) { |
|
316 x.swap(y); |
|
317 } |
|
318 |
|
319 } /* namespace boost */ |
|
320 |
|
321 #endif /*BOOST_ARRAY_HPP*/ |