]> git.donarmstrong.com Git - rsem.git/blob - boost/array.hpp
Updated boost to v1.55.0
[rsem.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  * 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)
27  *
28  * Jan 29, 2004
29  */
30 #ifndef BOOST_ARRAY_HPP
31 #define BOOST_ARRAY_HPP
32
33 #include <boost/detail/workaround.hpp>
34
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 
40 #endif
41
42 #include <cstddef>
43 #include <stdexcept>
44 #include <boost/assert.hpp>
45 #include <boost/swap.hpp>
46
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>
51 #include <algorithm>
52
53 // FIXES for broken compilers
54 #include <boost/config.hpp>
55
56
57 namespace boost {
58
59     template<class T, std::size_t N>
60     class array {
61       public:
62         T elems[N];    // fixed-size array of elements of type T
63
64       public:
65         // type definitions
66         typedef T              value_type;
67         typedef T*             iterator;
68         typedef const T*       const_iterator;
69         typedef T&             reference;
70         typedef const T&       const_reference;
71         typedef std::size_t    size_type;
72         typedef std::ptrdiff_t difference_type;
73
74         // iterator support
75         iterator        begin()       { return elems; }
76         const_iterator  begin() const { return elems; }
77         const_iterator cbegin() const { return elems; }
78         
79         iterator        end()       { return elems+N; }
80         const_iterator  end() const { return elems+N; }
81         const_iterator cend() const { return elems+N; }
82
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;
98 #else
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;
102 #endif
103
104         reverse_iterator rbegin() { return reverse_iterator(end()); }
105         const_reverse_iterator rbegin() const {
106             return const_reverse_iterator(end());
107         }
108         const_reverse_iterator crbegin() const {
109             return const_reverse_iterator(end());
110         }
111
112         reverse_iterator rend() { return reverse_iterator(begin()); }
113         const_reverse_iterator rend() const {
114             return const_reverse_iterator(begin());
115         }
116         const_reverse_iterator crend() const {
117             return const_reverse_iterator(begin());
118         }
119
120         // operator[]
121         reference operator[](size_type i) 
122         { 
123             BOOST_ASSERT_MSG( i < N, "out of range" );
124             return elems[i];
125         }
126         
127         const_reference operator[](size_type i) const 
128         {     
129             BOOST_ASSERT_MSG( i < N, "out of range" );
130             return elems[i]; 
131         }
132
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]; }
136     
137         // front() and back()
138         reference front() 
139         { 
140             return elems[0]; 
141         }
142         
143         const_reference front() const 
144         {
145             return elems[0];
146         }
147         
148         reference back() 
149         { 
150             return elems[N-1]; 
151         }
152         
153         const_reference back() const 
154         { 
155             return elems[N-1]; 
156         }
157
158         // size is constant
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 };
163
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]);
168         }
169
170         // direct access to data (read-only)
171         const T* data() const { return elems; }
172         T* data() { return elems; }
173
174         // use array as C array (direct read/write access to data)
175         T* c_array() { return elems; }
176
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());
181             return *this;
182         }
183
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)
187         {
188             std::fill_n(begin(),size(),value);
189         }
190
191         // check range (may be private because it is static)
192         static void rangecheck (size_type i) {
193             if (i >= size()) {
194                 std::out_of_range e("array<>: index out of range");
195                 boost::throw_exception(e);
196             }
197         }
198
199     };
200
201 #if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
202     template< class T >
203     class array< T, 0 > {
204
205       public:
206         // type definitions
207         typedef T              value_type;
208         typedef T*             iterator;
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;
214
215         // iterator support
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 ) ); }
219
220         iterator        end()       { return  begin(); }
221         const_iterator  end() const { return  begin(); }
222         const_iterator cend() const { return cbegin(); }
223
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;
239 #else
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;
243 #endif
244
245         reverse_iterator rbegin() { return reverse_iterator(end()); }
246         const_reverse_iterator rbegin() const {
247             return const_reverse_iterator(end());
248         }
249         const_reverse_iterator crbegin() const {
250             return const_reverse_iterator(end());
251         }
252
253         reverse_iterator rend() { return reverse_iterator(begin()); }
254         const_reverse_iterator rend() const {
255             return const_reverse_iterator(begin());
256         }
257         const_reverse_iterator crend() const {
258             return const_reverse_iterator(begin());
259         }
260
261         // operator[]
262         reference operator[](size_type /*i*/)
263         {
264             return failed_rangecheck();
265         }
266
267         const_reference operator[](size_type /*i*/) const
268         {
269             return failed_rangecheck();
270         }
271
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(); }
275
276         // front() and back()
277         reference front()
278         {
279             return failed_rangecheck();
280         }
281
282         const_reference front() const
283         {
284             return failed_rangecheck();
285         }
286
287         reference back()
288         {
289             return failed_rangecheck();
290         }
291
292         const_reference back() const
293         {
294             return failed_rangecheck();
295         }
296
297         // size is constant
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 };
302
303         void swap (array<T,0>& /*y*/) {
304         }
305
306         // direct access to data (read-only)
307         const T* data() const { return 0; }
308         T* data() { return 0; }
309
310         // use array as C array (direct read/write access to data)
311         T* c_array() { return 0; }
312
313         // assignment with type conversion
314         template <typename T2>
315         array<T,0>& operator= (const array<T2,0>& ) {
316             return *this;
317         }
318
319         // assign one value to all elements
320         void assign (const T& value) { fill ( value ); }
321         void fill   (const T& ) {}
322         
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__))
328                 //
329                 // We need to return something here to keep
330                 // some compilers happy: however we will never
331                 // actually get here....
332                 //
333                 static T placeholder;
334                 return placeholder;
335 #endif
336             }
337     };
338 #endif
339
340     // comparisons
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());
344     }
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());
348     }
349     template<class T, std::size_t N>
350     bool operator!= (const array<T,N>& x, const array<T,N>& y) {
351         return !(x==y);
352     }
353     template<class T, std::size_t N>
354     bool operator> (const array<T,N>& x, const array<T,N>& y) {
355         return y<x;
356     }
357     template<class T, std::size_t N>
358     bool operator<= (const array<T,N>& x, const array<T,N>& y) {
359         return !(y<x);
360     }
361     template<class T, std::size_t N>
362     bool operator>= (const array<T,N>& x, const array<T,N>& y) {
363         return !(x<y);
364     }
365
366     // global swap()
367     template<class T, std::size_t N>
368     inline void swap (array<T,N>& x, array<T,N>& y) {
369         x.swap(y);
370     }
371
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]'
375 //  
376 //  We can't just use this for all compilers, because the 
377 //      borland compilers can't handle this form. 
378     namespace detail {
379        template <typename T, std::size_t N> struct c_array
380        {
381            typedef T type[N];
382        };
383     }
384     
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)
388    {
389        return arg.elems;
390    }
391
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)
395    {
396        return arg.elems;
397    }
398 #else
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]
402     {
403         return arg.elems;
404     }
405     
406     // Const version.
407     template <typename T, std::size_t N>
408     const T(&get_c_array(const boost::array<T,N>& arg))[N]
409     {
410         return arg.elems;
411     }
412 #endif
413     
414 #if 0
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]
420     {
421         return static_cast<T(&)[N]>(arg);
422     }
423     
424     // Const version.
425     template <typename T, std::size_t N>
426     const T(&get_c_array(const std::array<T,N>& arg))[N]
427     {
428         return static_cast<T(&)[N]>(arg);
429     }
430 #endif
431
432
433     template<class T, std::size_t N>
434     std::size_t hash_value(const array<T,N>& arr)
435     {
436         return boost::hash_range(arr.begin(), arr.end());
437     }
438
439 } /* namespace boost */
440
441
442 #if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)  
443 # pragma warning(pop)  
444 #endif 
445
446 #endif /*BOOST_ARRAY_HPP*/