1 /* The following code declares class array,
2 * an STL container (as wrapper) for arrays of constant size.
5 * http://www.boost.org/libs/array/
8 * The original author site is at: http://www.josuttis.com/
10 * (C) Copyright Nicolai M. Josuttis 2001.
12 * Distributed under the Boost Software License, Version 1.0. (See
13 * accompanying file LICENSE_1_0.txt or copy at
14 * http://www.boost.org/LICENSE_1_0.txt)
16 * 14 Apr 2012 - (mtc) Added support for boost::hash
17 * 28 Dec 2010 - (mtc) Added cbegin and cend (and crbegin and crend) for C++Ox compatibility.
18 * 10 Mar 2010 - (mtc) fill method added, matching resolution of the standard library working group.
19 * See <http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#776> or Trac issue #3168
20 * Eventually, we should remove "assign" which is now a synonym for "fill" (Marshall Clow)
21 * 10 Mar 2010 - added workaround for SUNCC and !STLPort [trac #3893] (Marshall Clow)
22 * 29 Jan 2004 - c_array() added, BOOST_NO_PRIVATE_IN_AGGREGATE removed (Nico Josuttis)
23 * 23 Aug 2002 - fix for Non-MSVC compilers combined with MSVC libraries.
24 * 05 Aug 2001 - minor update (Nico Josuttis)
25 * 20 Jan 2001 - STLport fix (Beman Dawes)
26 * 29 Sep 2000 - Initial Revision (Nico Josuttis)
30 #ifndef BOOST_ARRAY_HPP
31 #define BOOST_ARRAY_HPP
33 #include <boost/detail/workaround.hpp>
35 #if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
36 # pragma warning(push)
37 # pragma warning(disable:4996) // 'std::equal': Function call with parameters that may be unsafe
38 # pragma warning(disable:4510) // boost::array<T,N>' : default constructor could not be generated
39 # pragma warning(disable:4610) // warning C4610: class 'boost::array<T,N>' can never be instantiated - user defined constructor required
44 #include <boost/assert.hpp>
45 #include <boost/swap.hpp>
47 // Handles broken standard libraries better than <iterator>
48 #include <boost/detail/iterator.hpp>
49 #include <boost/throw_exception.hpp>
50 #include <boost/functional/hash_fwd.hpp>
53 // FIXES for broken compilers
54 #include <boost/config.hpp>
59 template<class T, std::size_t N>
62 T elems[N]; // fixed-size array of elements of type T
68 typedef const T* const_iterator;
70 typedef const T& const_reference;
71 typedef std::size_t size_type;
72 typedef std::ptrdiff_t difference_type;
75 iterator begin() { return elems; }
76 const_iterator begin() const { return elems; }
77 const_iterator cbegin() const { return elems; }
79 iterator end() { return elems+N; }
80 const_iterator end() const { return elems+N; }
81 const_iterator cend() const { return elems+N; }
83 // reverse iterator support
84 #if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) && !defined(BOOST_MSVC_STD_ITERATOR) && !defined(BOOST_NO_STD_ITERATOR_TRAITS)
85 typedef std::reverse_iterator<iterator> reverse_iterator;
86 typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
87 #elif defined(_MSC_VER) && (_MSC_VER == 1300) && defined(BOOST_DINKUMWARE_STDLIB) && (BOOST_DINKUMWARE_STDLIB == 310)
88 // workaround for broken reverse_iterator in VC7
89 typedef std::reverse_iterator<std::_Ptrit<value_type, difference_type, iterator,
90 reference, iterator, reference> > reverse_iterator;
91 typedef std::reverse_iterator<std::_Ptrit<value_type, difference_type, const_iterator,
92 const_reference, iterator, reference> > const_reverse_iterator;
93 #elif defined(_RWSTD_NO_CLASS_PARTIAL_SPEC)
94 typedef std::reverse_iterator<iterator, std::random_access_iterator_tag,
95 value_type, reference, iterator, difference_type> reverse_iterator;
96 typedef std::reverse_iterator<const_iterator, std::random_access_iterator_tag,
97 value_type, const_reference, const_iterator, difference_type> const_reverse_iterator;
99 // workaround for broken reverse_iterator implementations
100 typedef std::reverse_iterator<iterator,T> reverse_iterator;
101 typedef std::reverse_iterator<const_iterator,T> const_reverse_iterator;
104 reverse_iterator rbegin() { return reverse_iterator(end()); }
105 const_reverse_iterator rbegin() const {
106 return const_reverse_iterator(end());
108 const_reverse_iterator crbegin() const {
109 return const_reverse_iterator(end());
112 reverse_iterator rend() { return reverse_iterator(begin()); }
113 const_reverse_iterator rend() const {
114 return const_reverse_iterator(begin());
116 const_reverse_iterator crend() const {
117 return const_reverse_iterator(begin());
121 reference operator[](size_type i)
123 BOOST_ASSERT_MSG( i < N, "out of range" );
127 const_reference operator[](size_type i) const
129 BOOST_ASSERT_MSG( i < N, "out of range" );
133 // at() with range check
134 reference at(size_type i) { rangecheck(i); return elems[i]; }
135 const_reference at(size_type i) const { rangecheck(i); return elems[i]; }
137 // front() and back()
143 const_reference front() const
153 const_reference back() const
159 static size_type size() { return N; }
160 static bool empty() { return false; }
161 static size_type max_size() { return N; }
162 enum { static_size = N };
164 // swap (note: linear complexity)
165 void swap (array<T,N>& y) {
166 for (size_type i = 0; i < N; ++i)
167 boost::swap(elems[i],y.elems[i]);
170 // direct access to data (read-only)
171 const T* data() const { return elems; }
172 T* data() { return elems; }
174 // use array as C array (direct read/write access to data)
175 T* c_array() { return elems; }
177 // assignment with type conversion
178 template <typename T2>
179 array<T,N>& operator= (const array<T2,N>& rhs) {
180 std::copy(rhs.begin(),rhs.end(), begin());
184 // assign one value to all elements
185 void assign (const T& value) { fill ( value ); } // A synonym for fill
186 void fill (const T& value)
188 std::fill_n(begin(),size(),value);
191 // check range (may be private because it is static)
192 static void rangecheck (size_type i) {
194 std::out_of_range e("array<>: index out of range");
195 boost::throw_exception(e);
201 #if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
203 class array< T, 0 > {
207 typedef T value_type;
209 typedef const T* const_iterator;
210 typedef T& reference;
211 typedef const T& const_reference;
212 typedef std::size_t size_type;
213 typedef std::ptrdiff_t difference_type;
216 iterator begin() { return iterator( reinterpret_cast< T * >( this ) ); }
217 const_iterator begin() const { return const_iterator( reinterpret_cast< const T * >( this ) ); }
218 const_iterator cbegin() const { return const_iterator( reinterpret_cast< const T * >( this ) ); }
220 iterator end() { return begin(); }
221 const_iterator end() const { return begin(); }
222 const_iterator cend() const { return cbegin(); }
224 // reverse iterator support
225 #if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) && !defined(BOOST_MSVC_STD_ITERATOR) && !defined(BOOST_NO_STD_ITERATOR_TRAITS)
226 typedef std::reverse_iterator<iterator> reverse_iterator;
227 typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
228 #elif defined(_MSC_VER) && (_MSC_VER == 1300) && defined(BOOST_DINKUMWARE_STDLIB) && (BOOST_DINKUMWARE_STDLIB == 310)
229 // workaround for broken reverse_iterator in VC7
230 typedef std::reverse_iterator<std::_Ptrit<value_type, difference_type, iterator,
231 reference, iterator, reference> > reverse_iterator;
232 typedef std::reverse_iterator<std::_Ptrit<value_type, difference_type, const_iterator,
233 const_reference, iterator, reference> > const_reverse_iterator;
234 #elif defined(_RWSTD_NO_CLASS_PARTIAL_SPEC)
235 typedef std::reverse_iterator<iterator, std::random_access_iterator_tag,
236 value_type, reference, iterator, difference_type> reverse_iterator;
237 typedef std::reverse_iterator<const_iterator, std::random_access_iterator_tag,
238 value_type, const_reference, const_iterator, difference_type> const_reverse_iterator;
240 // workaround for broken reverse_iterator implementations
241 typedef std::reverse_iterator<iterator,T> reverse_iterator;
242 typedef std::reverse_iterator<const_iterator,T> const_reverse_iterator;
245 reverse_iterator rbegin() { return reverse_iterator(end()); }
246 const_reverse_iterator rbegin() const {
247 return const_reverse_iterator(end());
249 const_reverse_iterator crbegin() const {
250 return const_reverse_iterator(end());
253 reverse_iterator rend() { return reverse_iterator(begin()); }
254 const_reverse_iterator rend() const {
255 return const_reverse_iterator(begin());
257 const_reverse_iterator crend() const {
258 return const_reverse_iterator(begin());
262 reference operator[](size_type /*i*/)
264 return failed_rangecheck();
267 const_reference operator[](size_type /*i*/) const
269 return failed_rangecheck();
272 // at() with range check
273 reference at(size_type /*i*/) { return failed_rangecheck(); }
274 const_reference at(size_type /*i*/) const { return failed_rangecheck(); }
276 // front() and back()
279 return failed_rangecheck();
282 const_reference front() const
284 return failed_rangecheck();
289 return failed_rangecheck();
292 const_reference back() const
294 return failed_rangecheck();
298 static size_type size() { return 0; }
299 static bool empty() { return true; }
300 static size_type max_size() { return 0; }
301 enum { static_size = 0 };
303 void swap (array<T,0>& /*y*/) {
306 // direct access to data (read-only)
307 const T* data() const { return 0; }
308 T* data() { return 0; }
310 // use array as C array (direct read/write access to data)
311 T* c_array() { return 0; }
313 // assignment with type conversion
314 template <typename T2>
315 array<T,0>& operator= (const array<T2,0>& ) {
319 // assign one value to all elements
320 void assign (const T& value) { fill ( value ); }
321 void fill (const T& ) {}
323 // check range (may be private because it is static)
324 static reference failed_rangecheck () {
325 std::out_of_range e("attempt to access element of an empty array");
326 boost::throw_exception(e);
327 #if defined(BOOST_NO_EXCEPTIONS) || (!defined(BOOST_MSVC) && !defined(__PATHSCALE__))
329 // We need to return something here to keep
330 // some compilers happy: however we will never
331 // actually get here....
333 static T placeholder;
341 template<class T, std::size_t N>
342 bool operator== (const array<T,N>& x, const array<T,N>& y) {
343 return std::equal(x.begin(), x.end(), y.begin());
345 template<class T, std::size_t N>
346 bool operator< (const array<T,N>& x, const array<T,N>& y) {
347 return std::lexicographical_compare(x.begin(),x.end(),y.begin(),y.end());
349 template<class T, std::size_t N>
350 bool operator!= (const array<T,N>& x, const array<T,N>& y) {
353 template<class T, std::size_t N>
354 bool operator> (const array<T,N>& x, const array<T,N>& y) {
357 template<class T, std::size_t N>
358 bool operator<= (const array<T,N>& x, const array<T,N>& y) {
361 template<class T, std::size_t N>
362 bool operator>= (const array<T,N>& x, const array<T,N>& y) {
367 template<class T, std::size_t N>
368 inline void swap (array<T,N>& x, array<T,N>& y) {
372 #if defined(__SUNPRO_CC)
373 // Trac ticket #4757; the Sun Solaris compiler can't handle
374 // syntax like 'T(&get_c_array(boost::array<T,N>& arg))[N]'
376 // We can't just use this for all compilers, because the
377 // borland compilers can't handle this form.
379 template <typename T, std::size_t N> struct c_array
385 // Specific for boost::array: simply returns its elems data member.
386 template <typename T, std::size_t N>
387 typename detail::c_array<T,N>::type& get_c_array(boost::array<T,N>& arg)
392 // Specific for boost::array: simply returns its elems data member.
393 template <typename T, std::size_t N>
394 typename const detail::c_array<T,N>::type& get_c_array(const boost::array<T,N>& arg)
399 // Specific for boost::array: simply returns its elems data member.
400 template <typename T, std::size_t N>
401 T(&get_c_array(boost::array<T,N>& arg))[N]
407 template <typename T, std::size_t N>
408 const T(&get_c_array(const boost::array<T,N>& arg))[N]
415 // Overload for std::array, assuming that std::array will have
416 // explicit conversion functions as discussed at the WG21 meeting
417 // in Summit, March 2009.
418 template <typename T, std::size_t N>
419 T(&get_c_array(std::array<T,N>& arg))[N]
421 return static_cast<T(&)[N]>(arg);
425 template <typename T, std::size_t N>
426 const T(&get_c_array(const std::array<T,N>& arg))[N]
428 return static_cast<T(&)[N]>(arg);
433 template<class T, std::size_t N>
434 std::size_t hash_value(const array<T,N>& arr)
436 return boost::hash_range(arr.begin(), arr.end());
439 } /* namespace boost */
442 #if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
443 # pragma warning(pop)
446 #endif /*BOOST_ARRAY_HPP*/