Imported Upstream version 1.64.0
[platform/upstream/boost.git] / boost / array.hpp
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
76         iterator        begin()       { return elems; }
77         const_iterator  begin() const { return elems; }
78         const_iterator cbegin() const { return elems; }
79         
80         iterator        end()       { return elems+N; }
81         const_iterator  end() const { return elems+N; }
82         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
99         reverse_iterator rbegin() { return reverse_iterator(end()); }
100         const_reverse_iterator rbegin() const {
101             return const_reverse_iterator(end());
102         }
103         const_reverse_iterator crbegin() const {
104             return const_reverse_iterator(end());
105         }
106
107         reverse_iterator rend() { return reverse_iterator(begin()); }
108         const_reverse_iterator rend() const {
109             return const_reverse_iterator(begin());
110         }
111         const_reverse_iterator crend() const {
112             return const_reverse_iterator(begin());
113         }
114
115         // operator[]
116         reference operator[](size_type i) 
117         { 
118             return BOOST_ASSERT_MSG( i < N, "out of range" ), elems[i]; 
119         }
120         
121         /*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
127         reference                           at(size_type i)       { return rangecheck(i), elems[i]; }
128         /*BOOST_CONSTEXPR*/ const_reference at(size_type i) const { return rangecheck(i), elems[i]; }
129     
130         // front() and back()
131         reference front() 
132         { 
133             return elems[0]; 
134         }
135         
136         BOOST_CONSTEXPR const_reference front() const 
137         {
138             return elems[0];
139         }
140         
141         reference back() 
142         { 
143             return elems[N-1]; 
144         }
145         
146         BOOST_CONSTEXPR const_reference back() const 
147         { 
148             return elems[N-1]; 
149         }
150
151         // size is constant
152         static BOOST_CONSTEXPR size_type size() { return N; }
153         static BOOST_CONSTEXPR bool empty() { return false; }
154         static BOOST_CONSTEXPR size_type max_size() { return N; }
155         enum { static_size = N };
156
157         // swap (note: linear complexity)
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)
164         const T* data() const { return elems; }
165         T* data() { return elems; }
166
167         // use array as C array (direct read/write access to data)
168         T* c_array() { return elems; }
169
170         // assignment with type conversion
171         template <typename T2>
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
178         void assign (const T& value) { fill ( value ); }    // A synonym for fill
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)
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
205         iterator        begin()       { return       iterator( reinterpret_cast<       T * >( this ) ); }
206         const_iterator  begin() const { return const_iterator( reinterpret_cast< const T * >( this ) ); }
207         const_iterator cbegin() const { return const_iterator( reinterpret_cast< const T * >( this ) ); }
208
209         iterator        end()       { return  begin(); }
210         const_iterator  end() const { return  begin(); }
211         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
228         reverse_iterator rbegin() { return reverse_iterator(end()); }
229         const_reverse_iterator rbegin() const {
230             return const_reverse_iterator(end());
231         }
232         const_reverse_iterator crbegin() const {
233             return const_reverse_iterator(end());
234         }
235
236         reverse_iterator rend() { return reverse_iterator(begin()); }
237         const_reverse_iterator rend() const {
238             return const_reverse_iterator(begin());
239         }
240         const_reverse_iterator crend() const {
241             return const_reverse_iterator(begin());
242         }
243
244         // operator[]
245         reference operator[](size_type /*i*/)
246         {
247             return failed_rangecheck();
248         }
249
250         /*BOOST_CONSTEXPR*/ const_reference operator[](size_type /*i*/) const
251         {
252             return failed_rangecheck();
253         }
254
255         // at() with range check
256         reference at(size_type /*i*/)               {   return failed_rangecheck(); }
257         /*BOOST_CONSTEXPR*/ const_reference at(size_type /*i*/) const   { return failed_rangecheck(); }
258
259         // front() and back()
260         reference front()
261         {
262             return failed_rangecheck();
263         }
264
265         BOOST_CONSTEXPR const_reference front() const
266         {
267             return failed_rangecheck();
268         }
269
270         reference back()
271         {
272             return failed_rangecheck();
273         }
274
275         BOOST_CONSTEXPR const_reference back() const
276         {
277             return failed_rangecheck();
278         }
279
280         // size is constant
281         static BOOST_CONSTEXPR size_type size() { return 0; }
282         static BOOST_CONSTEXPR bool empty() { return true; }
283         static BOOST_CONSTEXPR size_type max_size() { return 0; }
284         enum { static_size = 0 };
285
286         void swap (array<T,0>& /*y*/) {
287         }
288
289         // direct access to data (read-only)
290         const T* data() const { return 0; }
291         T* data() { return 0; }
292
293         // use array as C array (direct read/write access to data)
294         T* c_array() { return 0; }
295
296         // assignment with type conversion
297         template <typename T2>
298         array<T,0>& operator= (const array<T2,0>& ) {
299             return *this;
300         }
301
302         // assign one value to all elements
303         void assign (const T& value) { fill ( value ); }
304         void fill   (const T& ) {}
305         
306         // check range (may be private because it is static)
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>
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>
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>
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>
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>
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>
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>
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>
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>
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]
391     {
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>
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>
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>
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*/