1 // 2 // Boost.Pointer Container 3 // 4 // Copyright Thorsten Ottosen 2003-2005. Use, modification and 5 // distribution is subject to the Boost Software License, Version 6 // 1.0. (See accompanying file LICENSE_1_0.txt or copy at 7 // http://www.boost.org/LICENSE_1_0.txt) 8 // 9 // For more information, see http://www.boost.org/libs/ptr_container/ 10 // 11 12 #ifndef BOOST_PTR_CONTAINER_PTR_ARRAY_HPP 13 #define BOOST_PTR_CONTAINER_PTR_ARRAY_HPP 14 15 #if defined(_MSC_VER) && (_MSC_VER >= 1200) 16 # pragma once 17 #endif 18 19 #include <boost/array.hpp> 20 #include <boost/static_assert.hpp> 21 #include <boost/ptr_container/ptr_sequence_adapter.hpp> 22 #include <boost/ptr_container/detail/ptr_container_disable_deprecated.hpp> 23 24 #if defined(BOOST_PTR_CONTAINER_DISABLE_DEPRECATED) 25 #pragma GCC diagnostic push 26 #pragma GCC diagnostic ignored "-Wdeprecated-declarations" 27 #endif 28 29 namespace boost 30 { 31 32 namespace ptr_container_detail 33 { 34 template 35 < 36 class T, 37 size_t N, 38 class Allocator = int // dummy 39 > 40 class ptr_array_impl : public boost::array<T,N> 41 { 42 public: 43 typedef Allocator allocator_type; 44 ptr_array_impl(Allocator=Allocator ())45 ptr_array_impl( Allocator /*a*/ = Allocator() ) 46 { 47 this->assign( 0 ); 48 } 49 ptr_array_impl(size_t,T *,Allocator=Allocator ())50 ptr_array_impl( size_t, T*, Allocator /*a*/ = Allocator() ) 51 { 52 this->assign( 0 ); 53 } 54 }; 55 } 56 57 template 58 < 59 class T, 60 size_t N, 61 class CloneAllocator = heap_clone_allocator 62 > 63 class ptr_array : public 64 ptr_sequence_adapter< T, 65 ptr_container_detail::ptr_array_impl< 66 typename ptr_container_detail::void_ptr<T>::type,N>, 67 CloneAllocator > 68 { 69 private: 70 typedef ptr_sequence_adapter< T, 71 ptr_container_detail::ptr_array_impl< 72 typename ptr_container_detail::void_ptr<T>::type,N>, 73 CloneAllocator > 74 base_class; 75 76 typedef BOOST_DEDUCED_TYPENAME remove_nullable<T>::type U; 77 78 typedef ptr_array<T,N,CloneAllocator> 79 this_type; 80 81 public: 82 typedef std::size_t size_type; 83 typedef U* value_type; 84 typedef U* pointer; 85 typedef U& reference; 86 typedef const U& const_reference; 87 typedef BOOST_DEDUCED_TYPENAME base_class::auto_type 88 auto_type; 89 90 public: // constructors ptr_array()91 ptr_array() : base_class() 92 { } 93 ptr_array(const ptr_array & r)94 ptr_array( const ptr_array& r ) 95 { 96 size_t i = 0; 97 for( ; i != N; ++i ) 98 this->base()[i] = this->null_policy_allocate_clone( 99 static_cast<const U*>( &r[i] ) ); 100 } 101 102 template< class U > ptr_array(const ptr_array<U,N> & r)103 ptr_array( const ptr_array<U,N>& r ) 104 { 105 size_t i = 0; 106 for( ; i != N; ++i ) 107 this->base()[i] = this->null_policy_allocate_clone( 108 static_cast<const T*>( &r[i] ) ); 109 } 110 111 #ifndef BOOST_NO_AUTO_PTR ptr_array(std::auto_ptr<this_type> r)112 explicit ptr_array( std::auto_ptr<this_type> r ) 113 : base_class( r ) { } 114 #endif 115 #ifndef BOOST_NO_CXX11_SMART_PTR ptr_array(std::unique_ptr<this_type> r)116 explicit ptr_array( std::unique_ptr<this_type> r ) 117 : base_class( std::move( r ) ) { } 118 #endif 119 operator =(ptr_array r)120 ptr_array& operator=( ptr_array r ) 121 { 122 this->swap( r ); 123 return *this; 124 } 125 126 #ifndef BOOST_NO_AUTO_PTR operator =(std::auto_ptr<this_type> r)127 ptr_array& operator=( std::auto_ptr<this_type> r ) 128 { 129 base_class::operator=(r); 130 return *this; 131 } 132 #endif 133 #ifndef BOOST_NO_CXX11_SMART_PTR operator =(std::unique_ptr<this_type> r)134 ptr_array& operator=( std::unique_ptr<this_type> r ) 135 { 136 base_class::operator=(std::move(r)); 137 return *this; 138 } 139 #endif 140 141 #ifndef BOOST_NO_AUTO_PTR release()142 std::auto_ptr<this_type> release() 143 { 144 std::auto_ptr<this_type> ptr( new this_type ); 145 this->swap( *ptr ); 146 return ptr; 147 } 148 clone() const149 std::auto_ptr<this_type> clone() const 150 { 151 std::auto_ptr<this_type> pa( new this_type ); 152 clone_array_elements( *pa ); 153 return pa; 154 } 155 #else release()156 std::unique_ptr<this_type> release() 157 { 158 std::unique_ptr<this_type> ptr( new this_type ); 159 this->swap( *ptr ); 160 return ptr; 161 } 162 clone() const163 std::unique_ptr<this_type> clone() const 164 { 165 std::unique_ptr<this_type> pa( new this_type ); 166 clone_array_elements( *pa ); 167 return pa; 168 } 169 #endif 170 private: clone_array_elements(this_type & pa) const171 void clone_array_elements( this_type &pa ) const 172 { 173 for( size_t i = 0; i != N; ++i ) 174 { 175 if( !this->is_null(i) ) 176 pa.replace( i, pa.null_policy_allocate_clone( &(*this)[i] ) ); 177 } 178 } 179 180 private: // hide some members 181 using base_class::insert; 182 using base_class::erase; 183 using base_class::push_back; 184 using base_class::push_front; 185 using base_class::pop_front; 186 using base_class::pop_back; 187 using base_class::transfer; 188 using base_class::get_allocator; 189 190 public: // compile-time interface 191 192 template< size_t idx > replace(U * r)193 auto_type replace( U* r ) // strong 194 { 195 BOOST_STATIC_ASSERT( idx < N ); 196 197 this->enforce_null_policy( r, "Null pointer in 'ptr_array::replace()'" ); 198 auto_type res( static_cast<U*>(this->base()[idx]), *this ); // nothrow 199 this->base()[idx] = r; // nothrow 200 return boost::ptr_container::move(res); // nothrow 201 } 202 203 #ifndef BOOST_NO_AUTO_PTR 204 template< size_t idx, class V > replace(std::auto_ptr<V> r)205 auto_type replace( std::auto_ptr<V> r ) 206 { 207 return replace<idx>( r.release() ); 208 } 209 #endif 210 #ifndef BOOST_NO_CXX11_SMART_PTR 211 template< size_t idx, class V > replace(std::unique_ptr<V> r)212 auto_type replace( std::unique_ptr<V> r ) 213 { 214 return replace<idx>( r.release() ); 215 } 216 #endif 217 replace(size_t idx,U * r)218 auto_type replace( size_t idx, U* r ) // strong 219 { 220 this->enforce_null_policy( r, "Null pointer in 'ptr_array::replace()'" ); 221 222 auto_type ptr( r, *this ); 223 BOOST_PTR_CONTAINER_THROW_EXCEPTION( idx >= N, bad_index, 224 "'replace()' aout of bounds" ); 225 226 auto_type res( static_cast<U*>(this->base()[idx]), *this ); // nothrow 227 this->base()[idx] = ptr.release(); // nothrow 228 return boost::ptr_container::move(res); // nothrow 229 } 230 231 #ifndef BOOST_NO_AUTO_PTR 232 template< class V > replace(size_t idx,std::auto_ptr<V> r)233 auto_type replace( size_t idx, std::auto_ptr<V> r ) 234 { 235 return replace( idx, r.release() ); 236 } 237 #endif 238 #ifndef BOOST_NO_CXX11_SMART_PTR 239 template< class V > replace(size_t idx,std::unique_ptr<V> r)240 auto_type replace( size_t idx, std::unique_ptr<V> r ) 241 { 242 return replace( idx, r.release() ); 243 } 244 #endif 245 246 using base_class::at; 247 248 template< size_t idx > at()249 T& at() 250 { 251 BOOST_STATIC_ASSERT( idx < N ); 252 return (*this)[idx]; 253 } 254 255 template< size_t idx > at() const256 const T& at() const 257 { 258 BOOST_STATIC_ASSERT( idx < N ); 259 return (*this)[idx]; 260 } 261 is_null(size_t idx) const262 bool is_null( size_t idx ) const 263 { 264 return base_class::is_null(idx); 265 } 266 267 template< size_t idx > is_null() const268 bool is_null() const 269 { 270 BOOST_STATIC_ASSERT( idx < N ); 271 return this->base()[idx] == 0; 272 } 273 }; 274 275 ////////////////////////////////////////////////////////////////////////////// 276 // clonability 277 278 template< typename T, size_t size, typename CA > new_clone(const ptr_array<T,size,CA> & r)279 inline ptr_array<T,size,CA>* new_clone( const ptr_array<T,size,CA>& r ) 280 { 281 return r.clone().release(); 282 } 283 284 ///////////////////////////////////////////////////////////////////////// 285 // swap 286 287 template< typename T, size_t size, typename CA > swap(ptr_array<T,size,CA> & l,ptr_array<T,size,CA> & r)288 inline void swap( ptr_array<T,size,CA>& l, ptr_array<T,size,CA>& r ) 289 { 290 l.swap(r); 291 } 292 } 293 294 #if defined(BOOST_PTR_CONTAINER_DISABLE_DEPRECATED) 295 #pragma GCC diagnostic pop 296 #endif 297 298 #endif 299