1 /* The following code declares class array,
2  * an STL container (as wrapper) for arrays of constant size.
3  *
4  * See
5  *      http://www.boost.org/libs/array/
6  * for documentation.
7  *
8  * The original author site is at: http://www.josuttis.com/
9  *
10  * (C) Copyright Nicolai M. Josuttis 2001.
11  *
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  *  9 Jan 2013 - (mtc) Added constexpr
17  * 14 Apr 2012 - (mtc) Added support for boost::hash
18  * 28 Dec 2010 - (mtc) Added cbegin and cend (and crbegin and crend) for C++Ox compatibility.
19  * 10 Mar 2010 - (mtc) fill method added, matching resolution of the standard library working group.
20  *      See <http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#776> or Trac issue #3168
21  *      Eventually, we should remove "assign" which is now a synonym for "fill" (Marshall Clow)
22  * 10 Mar 2010 - added workaround for SUNCC and !STLPort [trac #3893] (Marshall Clow)
23  * 29 Jan 2004 - c_array() added, BOOST_NO_PRIVATE_IN_AGGREGATE removed (Nico Josuttis)
24  * 23 Aug 2002 - fix for Non-MSVC compilers combined with MSVC libraries.
25  * 05 Aug 2001 - minor update (Nico Josuttis)
26  * 20 Jan 2001 - STLport fix (Beman Dawes)
27  * 29 Sep 2000 - Initial Revision (Nico Josuttis)
28  *
29  * Jan 29, 2004
30  */
31 #ifndef BOOST_ARRAY_HPP
32 #define BOOST_ARRAY_HPP
33 
34 #include <boost/detail/workaround.hpp>
35 
36 #if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
37 # pragma warning(push)
38 # pragma warning(disable:4996) // 'std::equal': Function call with parameters that may be unsafe
39 # pragma warning(disable:4510) // boost::array<T,N>' : default constructor could not be generated
40 # pragma warning(disable:4610) // warning C4610: class 'boost::array<T,N>' can never be instantiated - user defined constructor required
41 #endif
42 
43 #include <cstddef>
44 #include <stdexcept>
45 #include <boost/assert.hpp>
46 #include <boost/static_assert.hpp>
47 #include <boost/swap.hpp>
48 
49 // Handles broken standard libraries better than <iterator>
50 #include <boost/detail/iterator.hpp>
51 #include <boost/throw_exception.hpp>
52 #include <algorithm>
53 
54 // FIXES for broken compilers
55 #include <boost/config.hpp>
56 
57 
58 namespace boost {
59 
60     template<class T, std::size_t N>
61     class array {
62       public:
63         T elems[N];    // fixed-size array of elements of type T
64 
65       public:
66         // type definitions
67         typedef T              value_type;
68         typedef T*             iterator;
69         typedef const T*       const_iterator;
70         typedef T&             reference;
71         typedef const T&       const_reference;
72         typedef std::size_t    size_type;
73         typedef std::ptrdiff_t difference_type;
74 
75         // iterator support
begin()76         iterator        begin()       { return elems; }
begin() const77         const_iterator  begin() const { return elems; }
cbegin() const78         const_iterator cbegin() const { return elems; }
79 
end()80         iterator        end()       { return elems+N; }
end() const81         const_iterator  end() const { return elems+N; }
cend() const82         const_iterator cend() const { return elems+N; }
83 
84         // reverse iterator support
85 #if !defined(BOOST_MSVC_STD_ITERATOR) && !defined(BOOST_NO_STD_ITERATOR_TRAITS)
86         typedef std::reverse_iterator<iterator> reverse_iterator;
87         typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
88 #elif defined(_RWSTD_NO_CLASS_PARTIAL_SPEC)
89         typedef std::reverse_iterator<iterator, std::random_access_iterator_tag,
90               value_type, reference, iterator, difference_type> reverse_iterator;
91         typedef std::reverse_iterator<const_iterator, std::random_access_iterator_tag,
92               value_type, const_reference, const_iterator, difference_type> const_reverse_iterator;
93 #else
94         // workaround for broken reverse_iterator implementations
95         typedef std::reverse_iterator<iterator,T> reverse_iterator;
96         typedef std::reverse_iterator<const_iterator,T> const_reverse_iterator;
97 #endif
98 
rbegin()99         reverse_iterator rbegin() { return reverse_iterator(end()); }
rbegin() const100         const_reverse_iterator rbegin() const {
101             return const_reverse_iterator(end());
102         }
crbegin() const103         const_reverse_iterator crbegin() const {
104             return const_reverse_iterator(end());
105         }
106 
rend()107         reverse_iterator rend() { return reverse_iterator(begin()); }
rend() const108         const_reverse_iterator rend() const {
109             return const_reverse_iterator(begin());
110         }
crend() const111         const_reverse_iterator crend() const {
112             return const_reverse_iterator(begin());
113         }
114 
115         // operator[]
operator [](size_type i)116         reference operator[](size_type i)
117         {
118             return BOOST_ASSERT_MSG( i < N, "out of range" ), elems[i];
119         }
120 
operator [](size_type i) const121         /*BOOST_CONSTEXPR*/ const_reference operator[](size_type i) const
122         {
123             return BOOST_ASSERT_MSG( i < N, "out of range" ), elems[i];
124         }
125 
126         // at() with range check
at(size_type i)127         reference                           at(size_type i)       { return rangecheck(i), elems[i]; }
at(size_type i) const128         /*BOOST_CONSTEXPR*/ const_reference at(size_type i) const { return rangecheck(i), elems[i]; }
129 
130         // front() and back()
front()131         reference front()
132         {
133             return elems[0];
134         }
135 
front() const136         BOOST_CONSTEXPR const_reference front() const
137         {
138             return elems[0];
139         }
140 
back()141         reference back()
142         {
143             return elems[N-1];
144         }
145 
back() const146         BOOST_CONSTEXPR const_reference back() const
147         {
148             return elems[N-1];
149         }
150 
151         // size is constant
size()152         static BOOST_CONSTEXPR size_type size() { return N; }
empty()153         static BOOST_CONSTEXPR bool empty() { return false; }
max_size()154         static BOOST_CONSTEXPR size_type max_size() { return N; }
155         enum { static_size = N };
156 
157         // swap (note: linear complexity)
swap(array<T,N> & y)158         void swap (array<T,N>& y) {
159             for (size_type i = 0; i < N; ++i)
160                 boost::swap(elems[i],y.elems[i]);
161         }
162 
163         // direct access to data (read-only)
data() const164         const T* data() const { return elems; }
data()165         T* data() { return elems; }
166 
167         // use array as C array (direct read/write access to data)
c_array()168         T* c_array() { return elems; }
169 
170         // assignment with type conversion
171         template <typename T2>
operator =(const array<T2,N> & rhs)172         array<T,N>& operator= (const array<T2,N>& rhs) {
173             std::copy(rhs.begin(),rhs.end(), begin());
174             return *this;
175         }
176 
177         // assign one value to all elements
assign(const T & value)178         void assign (const T& value) { fill ( value ); }    // A synonym for fill
fill(const T & value)179         void fill   (const T& value)
180         {
181             std::fill_n(begin(),size(),value);
182         }
183 
184         // check range (may be private because it is static)
rangecheck(size_type i)185         static BOOST_CONSTEXPR bool rangecheck (size_type i) {
186             return i >= size() ? boost::throw_exception(std::out_of_range ("array<>: index out of range")), true : true;
187         }
188 
189     };
190 
191     template< class T >
192     class array< T, 0 > {
193 
194       public:
195         // type definitions
196         typedef T              value_type;
197         typedef T*             iterator;
198         typedef const T*       const_iterator;
199         typedef T&             reference;
200         typedef const T&       const_reference;
201         typedef std::size_t    size_type;
202         typedef std::ptrdiff_t difference_type;
203 
204         // iterator support
begin()205         iterator        begin()       { return       iterator( reinterpret_cast<       T * >( this ) ); }
begin() const206         const_iterator  begin() const { return const_iterator( reinterpret_cast< const T * >( this ) ); }
cbegin() const207         const_iterator cbegin() const { return const_iterator( reinterpret_cast< const T * >( this ) ); }
208 
end()209         iterator        end()       { return  begin(); }
end() const210         const_iterator  end() const { return  begin(); }
cend() const211         const_iterator cend() const { return cbegin(); }
212 
213         // reverse iterator support
214 #if !defined(BOOST_MSVC_STD_ITERATOR) && !defined(BOOST_NO_STD_ITERATOR_TRAITS)
215         typedef std::reverse_iterator<iterator> reverse_iterator;
216         typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
217 #elif defined(_RWSTD_NO_CLASS_PARTIAL_SPEC)
218         typedef std::reverse_iterator<iterator, std::random_access_iterator_tag,
219               value_type, reference, iterator, difference_type> reverse_iterator;
220         typedef std::reverse_iterator<const_iterator, std::random_access_iterator_tag,
221               value_type, const_reference, const_iterator, difference_type> const_reverse_iterator;
222 #else
223         // workaround for broken reverse_iterator implementations
224         typedef std::reverse_iterator<iterator,T> reverse_iterator;
225         typedef std::reverse_iterator<const_iterator,T> const_reverse_iterator;
226 #endif
227 
rbegin()228         reverse_iterator rbegin() { return reverse_iterator(end()); }
rbegin() const229         const_reverse_iterator rbegin() const {
230             return const_reverse_iterator(end());
231         }
crbegin() const232         const_reverse_iterator crbegin() const {
233             return const_reverse_iterator(end());
234         }
235 
rend()236         reverse_iterator rend() { return reverse_iterator(begin()); }
rend() const237         const_reverse_iterator rend() const {
238             return const_reverse_iterator(begin());
239         }
crend() const240         const_reverse_iterator crend() const {
241             return const_reverse_iterator(begin());
242         }
243 
244         // operator[]
operator [](size_type)245         reference operator[](size_type /*i*/)
246         {
247             return failed_rangecheck();
248         }
249 
operator [](size_type) const250         /*BOOST_CONSTEXPR*/ const_reference operator[](size_type /*i*/) const
251         {
252             return failed_rangecheck();
253         }
254 
255         // at() with range check
at(size_type)256         reference at(size_type /*i*/)               {   return failed_rangecheck(); }
at(size_type) const257         /*BOOST_CONSTEXPR*/ const_reference at(size_type /*i*/) const   { return failed_rangecheck(); }
258 
259         // front() and back()
front()260         reference front()
261         {
262             return failed_rangecheck();
263         }
264 
front() const265         BOOST_CONSTEXPR const_reference front() const
266         {
267             return failed_rangecheck();
268         }
269 
back()270         reference back()
271         {
272             return failed_rangecheck();
273         }
274 
back() const275         BOOST_CONSTEXPR const_reference back() const
276         {
277             return failed_rangecheck();
278         }
279 
280         // size is constant
size()281         static BOOST_CONSTEXPR size_type size() { return 0; }
empty()282         static BOOST_CONSTEXPR bool empty() { return true; }
max_size()283         static BOOST_CONSTEXPR size_type max_size() { return 0; }
284         enum { static_size = 0 };
285 
swap(array<T,0> &)286         void swap (array<T,0>& /*y*/) {
287         }
288 
289         // direct access to data (read-only)
data() const290         const T* data() const { return 0; }
data()291         T* data() { return 0; }
292 
293         // use array as C array (direct read/write access to data)
c_array()294         T* c_array() { return 0; }
295 
296         // assignment with type conversion
297         template <typename T2>
operator =(const array<T2,0> &)298         array<T,0>& operator= (const array<T2,0>& ) {
299             return *this;
300         }
301 
302         // assign one value to all elements
assign(const T & value)303         void assign (const T& value) { fill ( value ); }
fill(const T &)304         void fill   (const T& ) {}
305 
306         // check range (may be private because it is static)
failed_rangecheck()307         static reference failed_rangecheck () {
308                 std::out_of_range e("attempt to access element of an empty array");
309                 boost::throw_exception(e);
310 #if defined(BOOST_NO_EXCEPTIONS) || (!defined(BOOST_MSVC) && !defined(__PATHSCALE__))
311                 //
312                 // We need to return something here to keep
313                 // some compilers happy: however we will never
314                 // actually get here....
315                 //
316                 static T placeholder;
317                 return placeholder;
318 #endif
319             }
320     };
321 
322     // comparisons
323     template<class T, std::size_t N>
operator ==(const array<T,N> & x,const array<T,N> & y)324     bool operator== (const array<T,N>& x, const array<T,N>& y) {
325         return std::equal(x.begin(), x.end(), y.begin());
326     }
327     template<class T, std::size_t N>
operator <(const array<T,N> & x,const array<T,N> & y)328     bool operator< (const array<T,N>& x, const array<T,N>& y) {
329         return std::lexicographical_compare(x.begin(),x.end(),y.begin(),y.end());
330     }
331     template<class T, std::size_t N>
operator !=(const array<T,N> & x,const array<T,N> & y)332     bool operator!= (const array<T,N>& x, const array<T,N>& y) {
333         return !(x==y);
334     }
335     template<class T, std::size_t N>
operator >(const array<T,N> & x,const array<T,N> & y)336     bool operator> (const array<T,N>& x, const array<T,N>& y) {
337         return y<x;
338     }
339     template<class T, std::size_t N>
operator <=(const array<T,N> & x,const array<T,N> & y)340     bool operator<= (const array<T,N>& x, const array<T,N>& y) {
341         return !(y<x);
342     }
343     template<class T, std::size_t N>
operator >=(const array<T,N> & x,const array<T,N> & y)344     bool operator>= (const array<T,N>& x, const array<T,N>& y) {
345         return !(x<y);
346     }
347 
348     // global swap()
349     template<class T, std::size_t N>
swap(array<T,N> & x,array<T,N> & y)350     inline void swap (array<T,N>& x, array<T,N>& y) {
351         x.swap(y);
352     }
353 
354 #if defined(__SUNPRO_CC)
355 //  Trac ticket #4757; the Sun Solaris compiler can't handle
356 //  syntax like 'T(&get_c_array(boost::array<T,N>& arg))[N]'
357 //
358 //  We can't just use this for all compilers, because the
359 //      borland compilers can't handle this form.
360     namespace detail {
361        template <typename T, std::size_t N> struct c_array
362        {
363            typedef T type[N];
364        };
365     }
366 
367    // Specific for boost::array: simply returns its elems data member.
368    template <typename T, std::size_t N>
get_c_array(boost::array<T,N> & arg)369    typename detail::c_array<T,N>::type& get_c_array(boost::array<T,N>& arg)
370    {
371        return arg.elems;
372    }
373 
374    // Specific for boost::array: simply returns its elems data member.
375    template <typename T, std::size_t N>
get_c_array(const boost::array<T,N> & arg)376    typename detail::c_array<T,N>::type const& get_c_array(const boost::array<T,N>& arg)
377    {
378        return arg.elems;
379    }
380 #else
381 // Specific for boost::array: simply returns its elems data member.
382     template <typename T, std::size_t N>
383     T(&get_c_array(boost::array<T,N>& arg))[N]
384     {
385         return arg.elems;
386     }
387 
388     // Const version.
389     template <typename T, std::size_t N>
390     const T(&get_c_array(const boost::array<T,N>& arg))[N]
__anona84a2afe0302null391     {
392         return arg.elems;
393     }
394 #endif
395 
396 #if 0
397     // Overload for std::array, assuming that std::array will have
398     // explicit conversion functions as discussed at the WG21 meeting
399     // in Summit, March 2009.
400     template <typename T, std::size_t N>
401     T(&get_c_array(std::array<T,N>& arg))[N]
402     {
403         return static_cast<T(&)[N]>(arg);
404     }
405 
406     // Const version.
407     template <typename T, std::size_t N>
408     const T(&get_c_array(const std::array<T,N>& arg))[N]
409     {
410         return static_cast<T(&)[N]>(arg);
411     }
412 #endif
413 
414     template <class It> std::size_t hash_range(It, It);
415 
416     template<class T, std::size_t N>
hash_value(const array<T,N> & arr)417     std::size_t hash_value(const array<T,N>& arr)
418     {
419         return boost::hash_range(arr.begin(), arr.end());
420     }
421 
422    template <size_t Idx, typename T, size_t N>
423    T &get(boost::array<T,N> &arr) BOOST_NOEXCEPT {
424        BOOST_STATIC_ASSERT_MSG ( Idx < N, "boost::get<>(boost::array &) index out of range" );
425        return arr[Idx];
426        }
427 
428    template <size_t Idx, typename T, size_t N>
get(const boost::array<T,N> & arr)429    const T &get(const boost::array<T,N> &arr) BOOST_NOEXCEPT {
430        BOOST_STATIC_ASSERT_MSG ( Idx < N, "boost::get<>(const boost::array &) index out of range" );
431        return arr[Idx];
432        }
433 
434 } /* namespace boost */
435 
436 #ifndef BOOST_NO_CXX11_HDR_ARRAY
437 //  If we don't have std::array, I'm assuming that we don't have std::get
438 namespace std {
439    template <size_t Idx, typename T, size_t N>
440    T &get(boost::array<T,N> &arr) BOOST_NOEXCEPT {
441        BOOST_STATIC_ASSERT_MSG ( Idx < N, "std::get<>(boost::array &) index out of range" );
442        return arr[Idx];
443        }
444 
445    template <size_t Idx, typename T, size_t N>
get(const boost::array<T,N> & arr)446    const T &get(const boost::array<T,N> &arr) BOOST_NOEXCEPT {
447        BOOST_STATIC_ASSERT_MSG ( Idx < N, "std::get<>(const boost::array &) index out of range" );
448        return arr[Idx];
449        }
450 }
451 #endif
452 
453 #if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
454 # pragma warning(pop)
455 #endif
456 
457 #endif /*BOOST_ARRAY_HPP*/
458