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