| // |
| // Boost.Pointer Container |
| // |
| // Copyright Thorsten Ottosen 2003-2005. Use, modification and |
| // distribution is subject to the Boost Software License, Version |
| // 1.0. (See accompanying file LICENSE_1_0.txt or copy at |
| // http://www.boost.org/LICENSE_1_0.txt) |
| // |
| // For more information, see http://www.boost.org/libs/ptr_container/ |
| // |
| |
| #ifndef BOOST_PTR_CONTAINER_PTR_ARRAY_HPP |
| #define BOOST_PTR_CONTAINER_PTR_ARRAY_HPP |
| |
| #if defined(_MSC_VER) && (_MSC_VER >= 1200) |
| # pragma once |
| #endif |
| |
| #include <boost/array.hpp> |
| #include <boost/static_assert.hpp> |
| #include <boost/ptr_container/ptr_sequence_adapter.hpp> |
| |
| namespace boost |
| { |
| |
| namespace ptr_container_detail |
| { |
| template |
| < |
| class T, |
| size_t N, |
| class Allocator = int // dummy |
| > |
| class ptr_array_impl : public boost::array<T,N> |
| { |
| public: |
| typedef Allocator allocator_type; |
| |
| ptr_array_impl( Allocator /*a*/ = Allocator() ) |
| { |
| this->assign( 0 ); |
| } |
| |
| ptr_array_impl( size_t, T*, Allocator /*a*/ = Allocator() ) |
| { |
| this->assign( 0 ); |
| } |
| }; |
| } |
| |
| template |
| < |
| class T, |
| size_t N, |
| class CloneAllocator = heap_clone_allocator |
| > |
| class ptr_array : public |
| ptr_sequence_adapter< T, |
| ptr_container_detail::ptr_array_impl<void*,N>, |
| CloneAllocator > |
| { |
| private: |
| typedef ptr_sequence_adapter< T, |
| ptr_container_detail::ptr_array_impl<void*,N>, |
| CloneAllocator > |
| base_class; |
| |
| typedef BOOST_DEDUCED_TYPENAME remove_nullable<T>::type U; |
| |
| typedef ptr_array<T,N,CloneAllocator> |
| this_type; |
| |
| public: |
| typedef std::size_t size_type; |
| typedef U* value_type; |
| typedef U* pointer; |
| typedef U& reference; |
| typedef const U& const_reference; |
| typedef BOOST_DEDUCED_TYPENAME base_class::auto_type |
| auto_type; |
| |
| public: // constructors |
| ptr_array() : base_class() |
| { } |
| |
| ptr_array( const ptr_array& r ) |
| { |
| size_t i = 0; |
| for( ; i != N; ++i ) |
| this->base()[i] = this->null_policy_allocate_clone( |
| static_cast<const T*>( &r[i] ) ); |
| } |
| |
| template< class U > |
| ptr_array( const ptr_array<U,N>& r ) |
| { |
| size_t i = 0; |
| for( ; i != N; ++i ) |
| this->base()[i] = this->null_policy_allocate_clone( |
| static_cast<const T*>( &r[i] ) ); |
| } |
| |
| explicit ptr_array( std::auto_ptr<this_type> r ) |
| : base_class( r ) { } |
| |
| ptr_array& operator=( ptr_array r ) |
| { |
| this->swap( r ); |
| return *this; |
| } |
| |
| ptr_array& operator=( std::auto_ptr<this_type> r ) |
| { |
| base_class::operator=(r); |
| return *this; |
| } |
| |
| std::auto_ptr<this_type> release() |
| { |
| std::auto_ptr<this_type> ptr( new this_type ); |
| this->swap( *ptr ); |
| return ptr; |
| } |
| |
| std::auto_ptr<this_type> clone() const |
| { |
| std::auto_ptr<this_type> pa( new this_type ); |
| for( size_t i = 0; i != N; ++i ) |
| { |
| if( ! is_null(i) ) |
| pa->replace( i, this->null_policy_allocate_clone( &(*this)[i] ) ); |
| } |
| return pa; |
| } |
| |
| private: // hide some members |
| using base_class::insert; |
| using base_class::erase; |
| using base_class::push_back; |
| using base_class::push_front; |
| using base_class::pop_front; |
| using base_class::pop_back; |
| using base_class::transfer; |
| using base_class::get_allocator; |
| |
| public: // compile-time interface |
| |
| template< size_t idx > |
| auto_type replace( U* r ) // strong |
| { |
| BOOST_STATIC_ASSERT( idx < N ); |
| |
| this->enforce_null_policy( r, "Null pointer in 'ptr_array::replace()'" ); |
| |
| auto_type res( static_cast<U*>( this->base()[idx] ) ); // nothrow |
| this->base()[idx] = r; // nothrow |
| return boost::ptr_container::move(res); // nothrow |
| } |
| |
| template< size_t idx, class V > |
| auto_type replace( std::auto_ptr<V> r ) |
| { |
| return replace<idx>( r.release() ); |
| } |
| |
| auto_type replace( size_t idx, U* r ) // strong |
| { |
| this->enforce_null_policy( r, "Null pointer in 'ptr_array::replace()'" ); |
| |
| auto_type ptr( r ); |
| |
| BOOST_PTR_CONTAINER_THROW_EXCEPTION( idx >= N, bad_index, |
| "'replace()' aout of bounds" ); |
| |
| auto_type res( static_cast<U*>( this->base()[idx] ) ); // nothrow |
| this->base()[idx] = ptr.release(); // nothrow |
| return boost::ptr_container::move(res); // nothrow |
| } |
| |
| template< class V > |
| auto_type replace( size_t idx, std::auto_ptr<V> r ) |
| { |
| return replace( idx, r.release() ); |
| } |
| |
| using base_class::at; |
| |
| template< size_t idx > |
| T& at() |
| { |
| BOOST_STATIC_ASSERT( idx < N ); |
| return (*this)[idx]; |
| } |
| |
| template< size_t idx > |
| const T& at() const |
| { |
| BOOST_STATIC_ASSERT( idx < N ); |
| return (*this)[idx]; |
| } |
| |
| bool is_null( size_t idx ) const |
| { |
| return base_class::is_null(idx); |
| } |
| |
| template< size_t idx > |
| bool is_null() const |
| { |
| BOOST_STATIC_ASSERT( idx < N ); |
| return this->base()[idx] == 0; |
| } |
| }; |
| |
| ////////////////////////////////////////////////////////////////////////////// |
| // clonability |
| |
| template< typename T, size_t size, typename CA > |
| inline ptr_array<T,size,CA>* new_clone( const ptr_array<T,size,CA>& r ) |
| { |
| return r.clone().release(); |
| } |
| |
| ///////////////////////////////////////////////////////////////////////// |
| // swap |
| |
| template< typename T, size_t size, typename CA > |
| inline void swap( ptr_array<T,size,CA>& l, ptr_array<T,size,CA>& r ) |
| { |
| l.swap(r); |
| } |
| } |
| |
| #endif |