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  * 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)
15  *
16  * 29 Jan 2004 - c_array() added, BOOST_NO_PRIVATE_IN_AGGREGATE removed (Nico Josuttis)
17  * 23 Aug 2002 - fix for Non-MSVC compilers combined with MSVC libraries.
18  * 05 Aug 2001 - minor update (Nico Josuttis)
19  * 20 Jan 2001 - STLport fix (Beman Dawes)
20  * 29 Sep 2000 - Initial Revision (Nico Josuttis)
21  *
22  * Jan 29, 2004
23  */
24 #ifndef BOOST_ARRAY_HPP
25 #define BOOST_ARRAY_HPP
26 
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 <algorithm>
34 
35 // FIXES for broken compilers
36 #include <boost/config.hpp>
37 
38 
39 namespace boost {
40 
41     template<class T, std::size_t N>
42     class array {
43       public:
44         T elems[N];    // fixed-size array of elements of type T
45 
46       public:
47         // type definitions
48         typedef T              value_type;
49         typedef T*             iterator;
50         typedef const T*       const_iterator;
51         typedef T&             reference;
52         typedef const T&       const_reference;
53         typedef std::size_t    size_type;
54         typedef std::ptrdiff_t difference_type;
55 
56         // iterator support
begin()57         iterator begin() { return elems; }
begin() const58         const_iterator begin() const { return elems; }
end()59         iterator end() { return elems+N; }
end() const60         const_iterator end() const { return elems+N; }
61 
62         // reverse iterator support
63 #if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) && !defined(BOOST_MSVC_STD_ITERATOR) && !defined(BOOST_NO_STD_ITERATOR_TRAITS)
64         typedef std::reverse_iterator<iterator> reverse_iterator;
65         typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
66 #elif defined(_MSC_VER) && (_MSC_VER == 1300) && defined(BOOST_DINKUMWARE_STDLIB) && (BOOST_DINKUMWARE_STDLIB == 310)
67         // workaround for broken reverse_iterator in VC7
68         typedef std::reverse_iterator<std::_Ptrit<value_type, difference_type, iterator,
69                                       reference, iterator, reference> > reverse_iterator;
70         typedef std::reverse_iterator<std::_Ptrit<value_type, difference_type, const_iterator,
71                                       const_reference, iterator, reference> > const_reverse_iterator;
72 #else
73         // workaround for broken reverse_iterator implementations
74         typedef std::reverse_iterator<iterator,T> reverse_iterator;
75         typedef std::reverse_iterator<const_iterator,T> const_reverse_iterator;
76 #endif
77 
rbegin()78         reverse_iterator rbegin() { return reverse_iterator(end()); }
rbegin() const79         const_reverse_iterator rbegin() const {
80             return const_reverse_iterator(end());
81         }
rend()82         reverse_iterator rend() { return reverse_iterator(begin()); }
rend() const83         const_reverse_iterator rend() const {
84             return const_reverse_iterator(begin());
85         }
86 
87         // operator[]
operator [](size_type i)88         reference operator[](size_type i)
89         {
90             BOOST_ASSERT( i < N && "out of range" );
91             return elems[i];
92         }
93 
operator [](size_type i) const94         const_reference operator[](size_type i) const
95         {
96             BOOST_ASSERT( i < N && "out of range" );
97             return elems[i];
98         }
99 
100         // at() with range check
at(size_type i)101         reference at(size_type i) { rangecheck(i); return elems[i]; }
at(size_type i) const102         const_reference at(size_type i) const { rangecheck(i); return elems[i]; }
103 
104         // front() and back()
front()105         reference front()
106         {
107             return elems[0];
108         }
109 
front() const110         const_reference front() const
111         {
112             return elems[0];
113         }
114 
back()115         reference back()
116         {
117             return elems[N-1];
118         }
119 
back() const120         const_reference back() const
121         {
122             return elems[N-1];
123         }
124 
125         // size is constant
size()126         static size_type size() { return N; }
empty()127         static bool empty() { return false; }
max_size()128         static size_type max_size() { return N; }
129         enum { static_size = N };
130 
131         // swap (note: linear complexity)
swap(array<T,N> & y)132         void swap (array<T,N>& y) {
133             std::swap_ranges(begin(),end(),y.begin());
134         }
135 
136         // direct access to data (read-only)
data() const137         const T* data() const { return elems; }
138 
139         // use array as C array (direct read/write access to data)
c_array()140         T* c_array() { return elems; }
141 
142         // assignment with type conversion
143         template <typename T2>
operator =(const array<T2,N> & rhs)144         array<T,N>& operator= (const array<T2,N>& rhs) {
145             std::copy(rhs.begin(),rhs.end(), begin());
146             return *this;
147         }
148 
149         // assign one value to all elements
assign(const T & value)150         void assign (const T& value)
151         {
152             std::fill_n(begin(),size(),value);
153         }
154 
155         // check range (may be private because it is static)
rangecheck(size_type i)156         static void rangecheck (size_type i) {
157             if (i >= size()) {
158                 throw std::range_error("array<>: index out of range");
159             }
160         }
161 
162     };
163 
164     // comparisons
165     template<class T, std::size_t N>
operator ==(const array<T,N> & x,const array<T,N> & y)166     bool operator== (const array<T,N>& x, const array<T,N>& y) {
167         return std::equal(x.begin(), x.end(), y.begin());
168     }
169     template<class T, std::size_t N>
operator <(const array<T,N> & x,const array<T,N> & y)170     bool operator< (const array<T,N>& x, const array<T,N>& y) {
171         return std::lexicographical_compare(x.begin(),x.end(),y.begin(),y.end());
172     }
173     template<class T, std::size_t N>
operator !=(const array<T,N> & x,const array<T,N> & y)174     bool operator!= (const array<T,N>& x, const array<T,N>& y) {
175         return !(x==y);
176     }
177     template<class T, std::size_t N>
operator >(const array<T,N> & x,const array<T,N> & y)178     bool operator> (const array<T,N>& x, const array<T,N>& y) {
179         return y<x;
180     }
181     template<class T, std::size_t N>
operator <=(const array<T,N> & x,const array<T,N> & y)182     bool operator<= (const array<T,N>& x, const array<T,N>& y) {
183         return !(y<x);
184     }
185     template<class T, std::size_t N>
operator >=(const array<T,N> & x,const array<T,N> & y)186     bool operator>= (const array<T,N>& x, const array<T,N>& y) {
187         return !(x<y);
188     }
189 
190     // global swap()
191     template<class T, std::size_t N>
swap(array<T,N> & x,array<T,N> & y)192     inline void swap (array<T,N>& x, array<T,N>& y) {
193         x.swap(y);
194     }
195 
196 } /* namespace boost */
197 
198 #endif /*BOOST_ARRAY_HPP*/
199