williamr@4: /* The following code declares class array, williamr@4: * an STL container (as wrapper) for arrays of constant size. williamr@4: * williamr@4: * See williamr@4: * http://www.boost.org/libs/array/ williamr@4: * for documentation. williamr@4: * williamr@4: * The original author site is at: http://www.josuttis.com/ williamr@4: * williamr@4: * (C) Copyright Nicolai M. Josuttis 2001. williamr@4: * williamr@4: * Distributed under the Boost Software License, Version 1.0. (See williamr@4: * accompanying file LICENSE_1_0.txt or copy at williamr@4: * http://www.boost.org/LICENSE_1_0.txt) williamr@4: * williamr@4: * 29 Jan 2004 - c_array() added, BOOST_NO_PRIVATE_IN_AGGREGATE removed (Nico Josuttis) williamr@4: * 23 Aug 2002 - fix for Non-MSVC compilers combined with MSVC libraries. williamr@4: * 05 Aug 2001 - minor update (Nico Josuttis) williamr@4: * 20 Jan 2001 - STLport fix (Beman Dawes) williamr@4: * 29 Sep 2000 - Initial Revision (Nico Josuttis) williamr@4: * williamr@4: * Jan 29, 2004 williamr@4: */ williamr@4: #ifndef BOOST_ARRAY_HPP williamr@4: #define BOOST_ARRAY_HPP williamr@4: williamr@4: #include williamr@4: #include williamr@4: #include williamr@4: williamr@4: // Handles broken standard libraries better than williamr@4: #include williamr@4: #include williamr@4: #include williamr@4: williamr@4: // FIXES for broken compilers williamr@4: #include williamr@4: williamr@4: williamr@4: namespace boost { williamr@4: williamr@4: template williamr@4: class array { williamr@4: public: williamr@4: T elems[N]; // fixed-size array of elements of type T williamr@4: williamr@4: public: williamr@4: // type definitions williamr@4: typedef T value_type; williamr@4: typedef T* iterator; williamr@4: typedef const T* const_iterator; williamr@4: typedef T& reference; williamr@4: typedef const T& const_reference; williamr@4: typedef std::size_t size_type; williamr@4: typedef std::ptrdiff_t difference_type; williamr@4: williamr@4: // iterator support williamr@4: iterator begin() { return elems; } williamr@4: const_iterator begin() const { return elems; } williamr@4: iterator end() { return elems+N; } williamr@4: const_iterator end() const { return elems+N; } williamr@4: williamr@4: // reverse iterator support williamr@4: #if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) && !defined(BOOST_MSVC_STD_ITERATOR) && !defined(BOOST_NO_STD_ITERATOR_TRAITS) williamr@4: typedef std::reverse_iterator reverse_iterator; williamr@4: typedef std::reverse_iterator const_reverse_iterator; williamr@4: #elif defined(_MSC_VER) && (_MSC_VER == 1300) && defined(BOOST_DINKUMWARE_STDLIB) && (BOOST_DINKUMWARE_STDLIB == 310) williamr@4: // workaround for broken reverse_iterator in VC7 williamr@4: typedef std::reverse_iterator > reverse_iterator; williamr@4: typedef std::reverse_iterator > const_reverse_iterator; williamr@4: #else williamr@4: // workaround for broken reverse_iterator implementations williamr@4: typedef std::reverse_iterator reverse_iterator; williamr@4: typedef std::reverse_iterator const_reverse_iterator; williamr@4: #endif williamr@4: williamr@4: reverse_iterator rbegin() { return reverse_iterator(end()); } williamr@4: const_reverse_iterator rbegin() const { williamr@4: return const_reverse_iterator(end()); williamr@4: } williamr@4: reverse_iterator rend() { return reverse_iterator(begin()); } williamr@4: const_reverse_iterator rend() const { williamr@4: return const_reverse_iterator(begin()); williamr@4: } williamr@4: williamr@4: // operator[] williamr@4: reference operator[](size_type i) williamr@4: { williamr@4: BOOST_ASSERT( i < N && "out of range" ); williamr@4: return elems[i]; williamr@4: } williamr@4: williamr@4: const_reference operator[](size_type i) const williamr@4: { williamr@4: BOOST_ASSERT( i < N && "out of range" ); williamr@4: return elems[i]; williamr@4: } williamr@4: williamr@4: // at() with range check williamr@4: reference at(size_type i) { rangecheck(i); return elems[i]; } williamr@4: const_reference at(size_type i) const { rangecheck(i); return elems[i]; } williamr@4: williamr@4: // front() and back() williamr@4: reference front() williamr@4: { williamr@4: return elems[0]; williamr@4: } williamr@4: williamr@4: const_reference front() const williamr@4: { williamr@4: return elems[0]; williamr@4: } williamr@4: williamr@4: reference back() williamr@4: { williamr@4: return elems[N-1]; williamr@4: } williamr@4: williamr@4: const_reference back() const williamr@4: { williamr@4: return elems[N-1]; williamr@4: } williamr@4: williamr@4: // size is constant williamr@4: static size_type size() { return N; } williamr@4: static bool empty() { return false; } williamr@4: static size_type max_size() { return N; } williamr@4: enum { static_size = N }; williamr@4: williamr@4: // swap (note: linear complexity) williamr@4: void swap (array& y) { williamr@4: std::swap_ranges(begin(),end(),y.begin()); williamr@4: } williamr@4: williamr@4: // direct access to data (read-only) williamr@4: const T* data() const { return elems; } williamr@4: T* data() { return elems; } williamr@4: williamr@4: // use array as C array (direct read/write access to data) williamr@4: T* c_array() { return elems; } williamr@4: williamr@4: // assignment with type conversion williamr@4: template williamr@4: array& operator= (const array& rhs) { williamr@4: std::copy(rhs.begin(),rhs.end(), begin()); williamr@4: return *this; williamr@4: } williamr@4: williamr@4: // assign one value to all elements williamr@4: void assign (const T& value) williamr@4: { williamr@4: std::fill_n(begin(),size(),value); williamr@4: } williamr@4: williamr@4: // check range (may be private because it is static) williamr@4: static void rangecheck (size_type i) { williamr@4: if (i >= size()) { williamr@4: throw std::range_error("array<>: index out of range"); williamr@4: } williamr@4: } williamr@4: williamr@4: }; williamr@4: williamr@4: #if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) williamr@4: template< class T > williamr@4: class array< T, 0 > { williamr@4: williamr@4: public: williamr@4: // type definitions williamr@4: typedef T value_type; williamr@4: typedef T* iterator; williamr@4: typedef const T* const_iterator; williamr@4: typedef T& reference; williamr@4: typedef const T& const_reference; williamr@4: typedef std::size_t size_type; williamr@4: typedef std::ptrdiff_t difference_type; williamr@4: williamr@4: // iterator support williamr@4: iterator begin() { return iterator( reinterpret_cast< T * >( this ) ); } williamr@4: const_iterator begin() const { return const_iterator( reinterpret_cast< const T * >( this ) ); } williamr@4: iterator end() { return begin(); } williamr@4: const_iterator end() const { return begin(); } williamr@4: williamr@4: // reverse iterator support williamr@4: #if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) && !defined(BOOST_MSVC_STD_ITERATOR) && !defined(BOOST_NO_STD_ITERATOR_TRAITS) williamr@4: typedef std::reverse_iterator reverse_iterator; williamr@4: typedef std::reverse_iterator const_reverse_iterator; williamr@4: #elif defined(_MSC_VER) && (_MSC_VER == 1300) && defined(BOOST_DINKUMWARE_STDLIB) && (BOOST_DINKUMWARE_STDLIB == 310) williamr@4: // workaround for broken reverse_iterator in VC7 williamr@4: typedef std::reverse_iterator > reverse_iterator; williamr@4: typedef std::reverse_iterator > const_reverse_iterator; williamr@4: #else williamr@4: // workaround for broken reverse_iterator implementations williamr@4: typedef std::reverse_iterator reverse_iterator; williamr@4: typedef std::reverse_iterator const_reverse_iterator; williamr@4: #endif williamr@4: williamr@4: reverse_iterator rbegin() { return reverse_iterator(end()); } williamr@4: const_reverse_iterator rbegin() const { williamr@4: return const_reverse_iterator(end()); williamr@4: } williamr@4: reverse_iterator rend() { return reverse_iterator(begin()); } williamr@4: const_reverse_iterator rend() const { williamr@4: return const_reverse_iterator(begin()); williamr@4: } williamr@4: williamr@4: // operator[] williamr@4: reference operator[](size_type i) williamr@4: { williamr@4: return failed_rangecheck(); williamr@4: } williamr@4: williamr@4: const_reference operator[](size_type i) const williamr@4: { williamr@4: return failed_rangecheck(); williamr@4: } williamr@4: williamr@4: // at() with range check williamr@4: reference at(size_type i) { return failed_rangecheck(); } williamr@4: const_reference at(size_type i) const { return failed_rangecheck(); } williamr@4: williamr@4: // front() and back() williamr@4: reference front() williamr@4: { williamr@4: return failed_rangecheck(); williamr@4: } williamr@4: williamr@4: const_reference front() const williamr@4: { williamr@4: return failed_rangecheck(); williamr@4: } williamr@4: williamr@4: reference back() williamr@4: { williamr@4: return failed_rangecheck(); williamr@4: } williamr@4: williamr@4: const_reference back() const williamr@4: { williamr@4: return failed_rangecheck(); williamr@4: } williamr@4: williamr@4: // size is constant williamr@4: static size_type size() { return 0; } williamr@4: static bool empty() { return true; } williamr@4: static size_type max_size() { return 0; } williamr@4: enum { static_size = 0 }; williamr@4: williamr@4: void swap (array& y) { williamr@4: } williamr@4: williamr@4: // direct access to data (read-only) williamr@4: const T* data() const { return 0; } williamr@4: T* data() { return 0; } williamr@4: williamr@4: // use array as C array (direct read/write access to data) williamr@4: T* c_array() { return 0; } williamr@4: williamr@4: // assignment with type conversion williamr@4: template williamr@4: array& operator= (const array& ) { williamr@4: return *this; williamr@4: } williamr@4: williamr@4: // assign one value to all elements williamr@4: void assign (const T& ) { } williamr@4: williamr@4: // check range (may be private because it is static) williamr@4: static reference failed_rangecheck () { williamr@4: std::range_error e("attempt to access element of an empty array"); williamr@4: boost::throw_exception(e); williamr@4: // williamr@4: // We need to return something here to keep williamr@4: // some compilers happy: however we will never williamr@4: // actually get here.... williamr@4: // williamr@4: static T placeholder; williamr@4: return placeholder; williamr@4: } williamr@4: }; williamr@4: #endif williamr@4: williamr@4: // comparisons williamr@4: template williamr@4: bool operator== (const array& x, const array& y) { williamr@4: return std::equal(x.begin(), x.end(), y.begin()); williamr@4: } williamr@4: template williamr@4: bool operator< (const array& x, const array& y) { williamr@4: return std::lexicographical_compare(x.begin(),x.end(),y.begin(),y.end()); williamr@4: } williamr@4: template williamr@4: bool operator!= (const array& x, const array& y) { williamr@4: return !(x==y); williamr@4: } williamr@4: template williamr@4: bool operator> (const array& x, const array& y) { williamr@4: return y williamr@4: bool operator<= (const array& x, const array& y) { williamr@4: return !(y williamr@4: bool operator>= (const array& x, const array& y) { williamr@4: return !(x williamr@4: inline void swap (array& x, array& y) { williamr@4: x.swap(y); williamr@4: } williamr@4: williamr@4: } /* namespace boost */ williamr@4: williamr@4: #endif /*BOOST_ARRAY_HPP*/