You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and dots ('.'), can be up to 35 characters long. Letters must be lowercase.
234 lines
6.4 KiB
234 lines
6.4 KiB
// |
|
// 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
|
|
|