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