Chris@16
|
1 //
|
Chris@16
|
2 // Boost.Pointer Container
|
Chris@16
|
3 //
|
Chris@16
|
4 // Copyright Thorsten Ottosen 2003-2005. Use, modification and
|
Chris@16
|
5 // distribution is subject to the Boost Software License, Version
|
Chris@16
|
6 // 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
Chris@16
|
7 // http://www.boost.org/LICENSE_1_0.txt)
|
Chris@16
|
8 //
|
Chris@16
|
9 // For more information, see http://www.boost.org/libs/ptr_container/
|
Chris@16
|
10 //
|
Chris@16
|
11
|
Chris@16
|
12
|
Chris@16
|
13 #ifndef BOOST_PTR_CONTAINER_DETAIL_REVERSIBLE_PTR_CONTAINER_HPP
|
Chris@16
|
14 #define BOOST_PTR_CONTAINER_DETAIL_REVERSIBLE_PTR_CONTAINER_HPP
|
Chris@16
|
15
|
Chris@16
|
16 #if defined(_MSC_VER) && (_MSC_VER >= 1200)
|
Chris@16
|
17 # pragma once
|
Chris@16
|
18 #endif
|
Chris@16
|
19
|
Chris@16
|
20 #include <boost/ptr_container/detail/throw_exception.hpp>
|
Chris@16
|
21 #include <boost/ptr_container/detail/scoped_deleter.hpp>
|
Chris@16
|
22 #include <boost/ptr_container/detail/static_move_ptr.hpp>
|
Chris@16
|
23 #include <boost/ptr_container/exception.hpp>
|
Chris@16
|
24 #include <boost/ptr_container/clone_allocator.hpp>
|
Chris@16
|
25 #include <boost/ptr_container/nullable.hpp>
|
Chris@16
|
26
|
Chris@16
|
27 #ifdef BOOST_NO_SFINAE
|
Chris@16
|
28 #else
|
Chris@16
|
29 #include <boost/range/functions.hpp>
|
Chris@16
|
30 #endif
|
Chris@16
|
31
|
Chris@16
|
32 #include <boost/config.hpp>
|
Chris@16
|
33 #include <boost/iterator/reverse_iterator.hpp>
|
Chris@16
|
34 #include <boost/range/iterator.hpp>
|
Chris@16
|
35 #include <boost/utility/enable_if.hpp>
|
Chris@16
|
36 #include <boost/type_traits/is_pointer.hpp>
|
Chris@16
|
37 #include <boost/type_traits/is_integral.hpp>
|
Chris@16
|
38 #include <typeinfo>
|
Chris@16
|
39 #include <memory>
|
Chris@16
|
40
|
Chris@16
|
41 #if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
|
Chris@16
|
42 #pragma warning(push)
|
Chris@16
|
43 #pragma warning(disable:4127)
|
Chris@16
|
44 #endif
|
Chris@16
|
45
|
Chris@16
|
46 namespace boost
|
Chris@16
|
47 {
|
Chris@16
|
48
|
Chris@16
|
49 namespace ptr_container_detail
|
Chris@16
|
50 {
|
Chris@16
|
51 template< class CloneAllocator >
|
Chris@16
|
52 struct clone_deleter
|
Chris@16
|
53 {
|
Chris@16
|
54 template< class T >
|
Chris@16
|
55 void operator()( const T* p ) const
|
Chris@16
|
56 {
|
Chris@16
|
57 CloneAllocator::deallocate_clone( p );
|
Chris@16
|
58 }
|
Chris@16
|
59 };
|
Chris@16
|
60
|
Chris@16
|
61 template< class T >
|
Chris@16
|
62 struct is_pointer_or_integral
|
Chris@16
|
63 {
|
Chris@16
|
64 BOOST_STATIC_CONSTANT(bool, value = is_pointer<T>::value || is_integral<T>::value );
|
Chris@16
|
65 };
|
Chris@16
|
66
|
Chris@16
|
67 struct is_pointer_or_integral_tag {};
|
Chris@16
|
68 struct is_range_tag {};
|
Chris@16
|
69 struct sequence_tag {};
|
Chris@16
|
70 struct fixed_length_sequence_tag : sequence_tag {};
|
Chris@16
|
71 struct associative_container_tag {};
|
Chris@16
|
72 struct ordered_associative_container_tag : associative_container_tag {};
|
Chris@16
|
73 struct unordered_associative_container_tag : associative_container_tag {};
|
Chris@16
|
74
|
Chris@16
|
75
|
Chris@16
|
76
|
Chris@16
|
77 template
|
Chris@16
|
78 <
|
Chris@16
|
79 class Config,
|
Chris@16
|
80 class CloneAllocator
|
Chris@16
|
81 >
|
Chris@16
|
82 class reversible_ptr_container
|
Chris@16
|
83 {
|
Chris@16
|
84 private:
|
Chris@16
|
85 BOOST_STATIC_CONSTANT( bool, allow_null = Config::allow_null );
|
Chris@16
|
86
|
Chris@16
|
87 typedef BOOST_DEDUCED_TYPENAME Config::value_type Ty_;
|
Chris@16
|
88
|
Chris@16
|
89 template< bool allow_null_values >
|
Chris@16
|
90 struct null_clone_allocator
|
Chris@16
|
91 {
|
Chris@16
|
92 template< class Iter >
|
Chris@16
|
93 static Ty_* allocate_clone_from_iterator( Iter i )
|
Chris@16
|
94 {
|
Chris@16
|
95 return allocate_clone( Config::get_const_pointer( i ) );
|
Chris@16
|
96 }
|
Chris@16
|
97
|
Chris@16
|
98 static Ty_* allocate_clone( const Ty_* x )
|
Chris@16
|
99 {
|
Chris@16
|
100 if( allow_null_values )
|
Chris@16
|
101 {
|
Chris@16
|
102 if( x == 0 )
|
Chris@16
|
103 return 0;
|
Chris@16
|
104 }
|
Chris@16
|
105 else
|
Chris@16
|
106 {
|
Chris@16
|
107 BOOST_ASSERT( x != 0 && "Cannot insert clone of null!" );
|
Chris@16
|
108 }
|
Chris@16
|
109
|
Chris@16
|
110 Ty_* res = CloneAllocator::allocate_clone( *x );
|
Chris@16
|
111 BOOST_ASSERT( typeid(*res) == typeid(*x) &&
|
Chris@16
|
112 "CloneAllocator::allocate_clone() does not clone the "
|
Chris@16
|
113 "object properly. Check that new_clone() is implemented"
|
Chris@16
|
114 " correctly" );
|
Chris@16
|
115 return res;
|
Chris@16
|
116 }
|
Chris@16
|
117
|
Chris@16
|
118 static void deallocate_clone( const Ty_* x )
|
Chris@16
|
119 {
|
Chris@16
|
120 if( allow_null_values )
|
Chris@16
|
121 {
|
Chris@16
|
122 if( x == 0 )
|
Chris@16
|
123 return;
|
Chris@16
|
124 }
|
Chris@16
|
125
|
Chris@16
|
126 CloneAllocator::deallocate_clone( x );
|
Chris@16
|
127 }
|
Chris@16
|
128 };
|
Chris@16
|
129
|
Chris@16
|
130 typedef BOOST_DEDUCED_TYPENAME Config::void_container_type Cont;
|
Chris@16
|
131 #if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
|
Chris@16
|
132 typedef null_clone_allocator<reversible_ptr_container::allow_null>
|
Chris@16
|
133 null_cloner_type;
|
Chris@16
|
134 #else
|
Chris@16
|
135 typedef null_clone_allocator<allow_null> null_cloner_type;
|
Chris@16
|
136 #endif
|
Chris@16
|
137 typedef clone_deleter<null_cloner_type> Deleter;
|
Chris@16
|
138
|
Chris@16
|
139 Cont c_;
|
Chris@16
|
140
|
Chris@16
|
141 public:
|
Chris@16
|
142 Cont& base() { return c_; }
|
Chris@16
|
143 protected: // having this public could break encapsulation
|
Chris@16
|
144 const Cont& base() const { return c_; }
|
Chris@16
|
145
|
Chris@16
|
146 public: // typedefs
|
Chris@16
|
147 typedef Ty_* value_type;
|
Chris@16
|
148 typedef Ty_* pointer;
|
Chris@16
|
149 typedef Ty_& reference;
|
Chris@16
|
150 typedef const Ty_& const_reference;
|
Chris@16
|
151
|
Chris@16
|
152 typedef BOOST_DEDUCED_TYPENAME Config::iterator
|
Chris@16
|
153 iterator;
|
Chris@16
|
154 typedef BOOST_DEDUCED_TYPENAME Config::const_iterator
|
Chris@16
|
155 const_iterator;
|
Chris@16
|
156 typedef boost::reverse_iterator< iterator >
|
Chris@16
|
157 reverse_iterator;
|
Chris@16
|
158 typedef boost::reverse_iterator< const_iterator >
|
Chris@16
|
159 const_reverse_iterator;
|
Chris@16
|
160 typedef BOOST_DEDUCED_TYPENAME Cont::difference_type
|
Chris@16
|
161 difference_type;
|
Chris@16
|
162 typedef BOOST_DEDUCED_TYPENAME Cont::size_type
|
Chris@16
|
163 size_type;
|
Chris@16
|
164 typedef BOOST_DEDUCED_TYPENAME Config::allocator_type
|
Chris@16
|
165 allocator_type;
|
Chris@16
|
166 typedef CloneAllocator clone_allocator_type;
|
Chris@16
|
167 typedef ptr_container_detail::static_move_ptr<Ty_,Deleter>
|
Chris@16
|
168 auto_type;
|
Chris@16
|
169
|
Chris@16
|
170 protected:
|
Chris@16
|
171
|
Chris@16
|
172 typedef ptr_container_detail::scoped_deleter<Ty_,null_cloner_type>
|
Chris@16
|
173 scoped_deleter;
|
Chris@16
|
174 typedef BOOST_DEDUCED_TYPENAME Cont::iterator
|
Chris@16
|
175 ptr_iterator;
|
Chris@16
|
176 typedef BOOST_DEDUCED_TYPENAME Cont::const_iterator
|
Chris@16
|
177 ptr_const_iterator;
|
Chris@16
|
178 private:
|
Chris@16
|
179
|
Chris@16
|
180 template< class InputIterator >
|
Chris@16
|
181 void copy( InputIterator first, InputIterator last )
|
Chris@16
|
182 {
|
Chris@16
|
183 std::copy( first, last, begin() );
|
Chris@16
|
184 }
|
Chris@16
|
185
|
Chris@16
|
186 void copy( const reversible_ptr_container& r )
|
Chris@16
|
187 {
|
Chris@16
|
188 copy( r.begin(), r.end() );
|
Chris@16
|
189 }
|
Chris@16
|
190
|
Chris@16
|
191 void copy_clones_and_release( scoped_deleter& sd ) // nothrow
|
Chris@16
|
192 {
|
Chris@16
|
193 BOOST_ASSERT( size_type( std::distance( sd.begin(), sd.end() ) ) == c_.size() );
|
Chris@16
|
194 std::copy( sd.begin(), sd.end(), c_.begin() );
|
Chris@16
|
195 sd.release();
|
Chris@16
|
196 }
|
Chris@16
|
197
|
Chris@16
|
198 template< class ForwardIterator >
|
Chris@16
|
199 void clone_assign( ForwardIterator first,
|
Chris@16
|
200 ForwardIterator last ) // strong
|
Chris@16
|
201 {
|
Chris@16
|
202 BOOST_ASSERT( first != last );
|
Chris@16
|
203 scoped_deleter sd( first, last ); // strong
|
Chris@16
|
204 copy_clones_and_release( sd ); // nothrow
|
Chris@16
|
205 }
|
Chris@16
|
206
|
Chris@16
|
207 template< class ForwardIterator >
|
Chris@16
|
208 void clone_back_insert( ForwardIterator first,
|
Chris@16
|
209 ForwardIterator last )
|
Chris@16
|
210 {
|
Chris@16
|
211 BOOST_ASSERT( first != last );
|
Chris@16
|
212 scoped_deleter sd( first, last );
|
Chris@16
|
213 insert_clones_and_release( sd, end() );
|
Chris@16
|
214 }
|
Chris@16
|
215
|
Chris@16
|
216 void remove_all()
|
Chris@16
|
217 {
|
Chris@16
|
218 remove( begin(), end() );
|
Chris@16
|
219 }
|
Chris@16
|
220
|
Chris@16
|
221 protected:
|
Chris@16
|
222
|
Chris@16
|
223 void insert_clones_and_release( scoped_deleter& sd,
|
Chris@16
|
224 iterator where ) // strong
|
Chris@16
|
225 {
|
Chris@16
|
226 //
|
Chris@16
|
227 // 'c_.insert' always provides the strong guarantee for T* elements
|
Chris@16
|
228 // since a copy constructor of a pointer cannot throw
|
Chris@16
|
229 //
|
Chris@16
|
230 c_.insert( where.base(),
|
Chris@16
|
231 sd.begin(), sd.end() );
|
Chris@16
|
232 sd.release();
|
Chris@16
|
233 }
|
Chris@16
|
234
|
Chris@16
|
235 void insert_clones_and_release( scoped_deleter& sd ) // strong
|
Chris@16
|
236 {
|
Chris@16
|
237 c_.insert( sd.begin(), sd.end() );
|
Chris@16
|
238 sd.release();
|
Chris@16
|
239 }
|
Chris@16
|
240
|
Chris@16
|
241 template< class U >
|
Chris@16
|
242 void remove( U* ptr )
|
Chris@16
|
243 {
|
Chris@16
|
244 null_policy_deallocate_clone( ptr );
|
Chris@16
|
245 }
|
Chris@16
|
246
|
Chris@16
|
247 template< class I >
|
Chris@16
|
248 void remove( I i )
|
Chris@16
|
249 {
|
Chris@16
|
250 null_policy_deallocate_clone( Config::get_const_pointer(i) );
|
Chris@16
|
251 }
|
Chris@16
|
252
|
Chris@16
|
253 template< class I >
|
Chris@16
|
254 void remove( I first, I last )
|
Chris@16
|
255 {
|
Chris@16
|
256 for( ; first != last; ++first )
|
Chris@16
|
257 remove( first );
|
Chris@16
|
258 }
|
Chris@16
|
259
|
Chris@16
|
260 static void enforce_null_policy( const Ty_* x, const char* msg )
|
Chris@16
|
261 {
|
Chris@16
|
262 if( !allow_null )
|
Chris@16
|
263 {
|
Chris@16
|
264 BOOST_PTR_CONTAINER_THROW_EXCEPTION( 0 == x && "null not allowed",
|
Chris@16
|
265 bad_pointer, msg );
|
Chris@16
|
266 }
|
Chris@16
|
267 }
|
Chris@16
|
268
|
Chris@16
|
269 static Ty_* null_policy_allocate_clone( const Ty_* x )
|
Chris@16
|
270 {
|
Chris@16
|
271 return null_cloner_type::allocate_clone( x );
|
Chris@16
|
272 }
|
Chris@16
|
273
|
Chris@16
|
274 static void null_policy_deallocate_clone( const Ty_* x )
|
Chris@16
|
275 {
|
Chris@16
|
276 null_cloner_type::deallocate_clone( x );
|
Chris@16
|
277 }
|
Chris@16
|
278
|
Chris@16
|
279 private:
|
Chris@16
|
280 template< class ForwardIterator >
|
Chris@16
|
281 ForwardIterator advance( ForwardIterator begin, size_type n )
|
Chris@16
|
282 {
|
Chris@16
|
283 ForwardIterator iter = begin;
|
Chris@16
|
284 std::advance( iter, n );
|
Chris@16
|
285 return iter;
|
Chris@16
|
286 }
|
Chris@16
|
287
|
Chris@16
|
288 template< class I >
|
Chris@16
|
289 void constructor_impl( I first, I last, std::input_iterator_tag ) // basic
|
Chris@16
|
290 {
|
Chris@16
|
291 while( first != last )
|
Chris@16
|
292 {
|
Chris@16
|
293 insert( end(), null_cloner_type::allocate_clone_from_iterator(first) );
|
Chris@16
|
294 ++first;
|
Chris@16
|
295 }
|
Chris@16
|
296 }
|
Chris@16
|
297
|
Chris@16
|
298 template< class I >
|
Chris@16
|
299 void constructor_impl( I first, I last, std::forward_iterator_tag ) // strong
|
Chris@16
|
300 {
|
Chris@16
|
301 if( first == last )
|
Chris@16
|
302 return;
|
Chris@16
|
303 clone_back_insert( first, last );
|
Chris@16
|
304 }
|
Chris@16
|
305
|
Chris@16
|
306 template< class I >
|
Chris@16
|
307 void associative_constructor_impl( I first, I last ) // strong
|
Chris@16
|
308 {
|
Chris@16
|
309 if( first == last )
|
Chris@16
|
310 return;
|
Chris@16
|
311
|
Chris@16
|
312 scoped_deleter sd( first, last );
|
Chris@16
|
313 insert_clones_and_release( sd );
|
Chris@16
|
314 }
|
Chris@16
|
315
|
Chris@16
|
316 public: // foundation! should be protected!
|
Chris@16
|
317 reversible_ptr_container()
|
Chris@16
|
318 { }
|
Chris@16
|
319
|
Chris@16
|
320 template< class SizeType >
|
Chris@16
|
321 reversible_ptr_container( SizeType n, unordered_associative_container_tag )
|
Chris@16
|
322 : c_( n )
|
Chris@16
|
323 { }
|
Chris@16
|
324
|
Chris@16
|
325 template< class SizeType >
|
Chris@16
|
326 reversible_ptr_container( SizeType n, fixed_length_sequence_tag )
|
Chris@16
|
327 : c_( n )
|
Chris@16
|
328 { }
|
Chris@16
|
329
|
Chris@16
|
330 template< class SizeType >
|
Chris@16
|
331 reversible_ptr_container( SizeType n, const allocator_type& a,
|
Chris@16
|
332 fixed_length_sequence_tag )
|
Chris@16
|
333 : c_( n, a )
|
Chris@16
|
334 { }
|
Chris@16
|
335
|
Chris@16
|
336 explicit reversible_ptr_container( const allocator_type& a )
|
Chris@16
|
337 : c_( a )
|
Chris@16
|
338 { }
|
Chris@16
|
339
|
Chris@16
|
340 template< class PtrContainer >
|
Chris@16
|
341 explicit reversible_ptr_container( std::auto_ptr<PtrContainer> clone )
|
Chris@16
|
342 {
|
Chris@16
|
343 swap( *clone );
|
Chris@16
|
344 }
|
Chris@16
|
345
|
Chris@16
|
346 reversible_ptr_container( const reversible_ptr_container& r )
|
Chris@16
|
347 {
|
Chris@16
|
348 constructor_impl( r.begin(), r.end(), std::forward_iterator_tag() );
|
Chris@16
|
349 }
|
Chris@16
|
350
|
Chris@16
|
351 template< class C, class V >
|
Chris@16
|
352 reversible_ptr_container( const reversible_ptr_container<C,V>& r )
|
Chris@16
|
353 {
|
Chris@16
|
354 constructor_impl( r.begin(), r.end(), std::forward_iterator_tag() );
|
Chris@16
|
355 }
|
Chris@16
|
356
|
Chris@16
|
357 template< class PtrContainer >
|
Chris@16
|
358 reversible_ptr_container& operator=( std::auto_ptr<PtrContainer> clone ) // nothrow
|
Chris@16
|
359 {
|
Chris@16
|
360 swap( *clone );
|
Chris@16
|
361 return *this;
|
Chris@16
|
362 }
|
Chris@16
|
363
|
Chris@16
|
364 reversible_ptr_container& operator=( reversible_ptr_container r ) // strong
|
Chris@16
|
365 {
|
Chris@16
|
366 swap( r );
|
Chris@16
|
367 return *this;
|
Chris@16
|
368 }
|
Chris@16
|
369
|
Chris@16
|
370 // overhead: null-initilization of container pointer (very cheap compared to cloning)
|
Chris@16
|
371 // overhead: 1 heap allocation (very cheap compared to cloning)
|
Chris@16
|
372 template< class InputIterator >
|
Chris@16
|
373 reversible_ptr_container( InputIterator first,
|
Chris@16
|
374 InputIterator last,
|
Chris@16
|
375 const allocator_type& a = allocator_type() ) // basic, strong
|
Chris@16
|
376 : c_( a )
|
Chris@16
|
377 {
|
Chris@16
|
378 constructor_impl( first, last,
|
Chris@16
|
379 #if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
|
Chris@16
|
380 #else
|
Chris@16
|
381 BOOST_DEDUCED_TYPENAME
|
Chris@16
|
382 #endif
|
Chris@16
|
383 iterator_category<InputIterator>::type() );
|
Chris@16
|
384 }
|
Chris@16
|
385
|
Chris@16
|
386 template< class Compare >
|
Chris@16
|
387 reversible_ptr_container( const Compare& comp,
|
Chris@16
|
388 const allocator_type& a )
|
Chris@16
|
389 : c_( comp, a ) {}
|
Chris@16
|
390
|
Chris@16
|
391 template< class ForwardIterator >
|
Chris@16
|
392 reversible_ptr_container( ForwardIterator first,
|
Chris@16
|
393 ForwardIterator last,
|
Chris@16
|
394 fixed_length_sequence_tag )
|
Chris@16
|
395 : c_( std::distance(first,last) )
|
Chris@16
|
396 {
|
Chris@16
|
397 constructor_impl( first, last,
|
Chris@16
|
398 std::forward_iterator_tag() );
|
Chris@16
|
399 }
|
Chris@16
|
400
|
Chris@16
|
401 template< class SizeType, class InputIterator >
|
Chris@16
|
402 reversible_ptr_container( SizeType n,
|
Chris@16
|
403 InputIterator first,
|
Chris@16
|
404 InputIterator last,
|
Chris@16
|
405 fixed_length_sequence_tag )
|
Chris@16
|
406 : c_( n )
|
Chris@16
|
407 {
|
Chris@16
|
408 constructor_impl( first, last,
|
Chris@16
|
409 #if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
|
Chris@16
|
410 #else
|
Chris@16
|
411 BOOST_DEDUCED_TYPENAME
|
Chris@16
|
412 #endif
|
Chris@16
|
413 iterator_category<InputIterator>::type() );
|
Chris@16
|
414 }
|
Chris@16
|
415
|
Chris@16
|
416 template< class Compare >
|
Chris@16
|
417 reversible_ptr_container( const Compare& comp,
|
Chris@16
|
418 const allocator_type& a,
|
Chris@16
|
419 associative_container_tag )
|
Chris@16
|
420 : c_( comp, a )
|
Chris@16
|
421 { }
|
Chris@16
|
422
|
Chris@16
|
423 template< class InputIterator >
|
Chris@16
|
424 reversible_ptr_container( InputIterator first,
|
Chris@16
|
425 InputIterator last,
|
Chris@16
|
426 associative_container_tag )
|
Chris@16
|
427 {
|
Chris@16
|
428 associative_constructor_impl( first, last );
|
Chris@16
|
429 }
|
Chris@16
|
430
|
Chris@16
|
431 template< class InputIterator, class Compare >
|
Chris@16
|
432 reversible_ptr_container( InputIterator first,
|
Chris@16
|
433 InputIterator last,
|
Chris@16
|
434 const Compare& comp,
|
Chris@16
|
435 const allocator_type& a,
|
Chris@16
|
436 associative_container_tag )
|
Chris@16
|
437 : c_( comp, a )
|
Chris@16
|
438 {
|
Chris@16
|
439 associative_constructor_impl( first, last );
|
Chris@16
|
440 }
|
Chris@16
|
441
|
Chris@16
|
442 explicit reversible_ptr_container( size_type n )
|
Chris@16
|
443 : c_( n ) {}
|
Chris@16
|
444
|
Chris@16
|
445 template< class Hash, class Pred >
|
Chris@16
|
446 reversible_ptr_container( const Hash& h,
|
Chris@16
|
447 const Pred& pred,
|
Chris@16
|
448 const allocator_type& a )
|
Chris@16
|
449 : c_( h, pred, a ) {}
|
Chris@16
|
450
|
Chris@16
|
451 template< class InputIterator, class Hash, class Pred >
|
Chris@16
|
452 reversible_ptr_container( InputIterator first,
|
Chris@16
|
453 InputIterator last,
|
Chris@16
|
454 const Hash& h,
|
Chris@16
|
455 const Pred& pred,
|
Chris@16
|
456 const allocator_type& a )
|
Chris@16
|
457 : c_( h, pred, a )
|
Chris@16
|
458 {
|
Chris@16
|
459 associative_constructor_impl( first, last );
|
Chris@16
|
460 }
|
Chris@16
|
461
|
Chris@16
|
462 public:
|
Chris@16
|
463 ~reversible_ptr_container()
|
Chris@16
|
464 {
|
Chris@16
|
465 remove_all();
|
Chris@16
|
466 }
|
Chris@16
|
467
|
Chris@16
|
468 public:
|
Chris@16
|
469
|
Chris@16
|
470 allocator_type get_allocator() const
|
Chris@16
|
471 {
|
Chris@16
|
472 return c_.get_allocator();
|
Chris@16
|
473 }
|
Chris@16
|
474
|
Chris@16
|
475 public: // container requirements
|
Chris@16
|
476 iterator begin()
|
Chris@16
|
477 { return iterator( c_.begin() ); }
|
Chris@16
|
478 const_iterator begin() const
|
Chris@16
|
479 { return const_iterator( c_.begin() ); }
|
Chris@16
|
480 iterator end()
|
Chris@16
|
481 { return iterator( c_.end() ); }
|
Chris@16
|
482 const_iterator end() const
|
Chris@16
|
483 { return const_iterator( c_.end() ); }
|
Chris@16
|
484
|
Chris@16
|
485 reverse_iterator rbegin()
|
Chris@16
|
486 { return reverse_iterator( this->end() ); }
|
Chris@16
|
487 const_reverse_iterator rbegin() const
|
Chris@16
|
488 { return const_reverse_iterator( this->end() ); }
|
Chris@16
|
489 reverse_iterator rend()
|
Chris@16
|
490 { return reverse_iterator( this->begin() ); }
|
Chris@16
|
491 const_reverse_iterator rend() const
|
Chris@16
|
492 { return const_reverse_iterator( this->begin() ); }
|
Chris@16
|
493
|
Chris@16
|
494 const_iterator cbegin() const
|
Chris@16
|
495 { return const_iterator( c_.begin() ); }
|
Chris@16
|
496 const_iterator cend() const
|
Chris@16
|
497 { return const_iterator( c_.end() ); }
|
Chris@16
|
498
|
Chris@16
|
499 const_reverse_iterator crbegin() const
|
Chris@16
|
500 { return const_reverse_iterator( this->end() ); }
|
Chris@16
|
501 const_reverse_iterator crend() const
|
Chris@16
|
502 { return const_reverse_iterator( this->begin() ); }
|
Chris@16
|
503
|
Chris@16
|
504 void swap( reversible_ptr_container& r ) // nothrow
|
Chris@16
|
505 {
|
Chris@16
|
506 c_.swap( r.c_ );
|
Chris@16
|
507 }
|
Chris@16
|
508
|
Chris@16
|
509 size_type size() const // nothrow
|
Chris@16
|
510 {
|
Chris@16
|
511 return c_.size();
|
Chris@16
|
512 }
|
Chris@16
|
513
|
Chris@16
|
514 size_type max_size() const // nothrow
|
Chris@16
|
515 {
|
Chris@16
|
516 return c_.max_size();
|
Chris@16
|
517 }
|
Chris@16
|
518
|
Chris@16
|
519 bool empty() const // nothrow
|
Chris@16
|
520 {
|
Chris@16
|
521 return c_.empty();
|
Chris@16
|
522 }
|
Chris@16
|
523
|
Chris@16
|
524 public: // optional container requirements
|
Chris@16
|
525
|
Chris@16
|
526 bool operator==( const reversible_ptr_container& r ) const // nothrow
|
Chris@16
|
527 {
|
Chris@16
|
528 if( size() != r.size() )
|
Chris@16
|
529 return false;
|
Chris@16
|
530 else
|
Chris@16
|
531 return std::equal( begin(), end(), r.begin() );
|
Chris@16
|
532 }
|
Chris@16
|
533
|
Chris@16
|
534 bool operator!=( const reversible_ptr_container& r ) const // nothrow
|
Chris@16
|
535 {
|
Chris@16
|
536 return !(*this == r);
|
Chris@16
|
537 }
|
Chris@16
|
538
|
Chris@16
|
539 bool operator<( const reversible_ptr_container& r ) const // nothrow
|
Chris@16
|
540 {
|
Chris@16
|
541 return std::lexicographical_compare( begin(), end(), r.begin(), r.end() );
|
Chris@16
|
542 }
|
Chris@16
|
543
|
Chris@16
|
544 bool operator<=( const reversible_ptr_container& r ) const // nothrow
|
Chris@16
|
545 {
|
Chris@16
|
546 return !(r < *this);
|
Chris@16
|
547 }
|
Chris@16
|
548
|
Chris@16
|
549 bool operator>( const reversible_ptr_container& r ) const // nothrow
|
Chris@16
|
550 {
|
Chris@16
|
551 return r < *this;
|
Chris@16
|
552 }
|
Chris@16
|
553
|
Chris@16
|
554 bool operator>=( const reversible_ptr_container& r ) const // nothrow
|
Chris@16
|
555 {
|
Chris@16
|
556 return !(*this < r);
|
Chris@16
|
557 }
|
Chris@16
|
558
|
Chris@16
|
559 public: // modifiers
|
Chris@16
|
560
|
Chris@16
|
561 iterator insert( iterator before, Ty_* x )
|
Chris@16
|
562 {
|
Chris@16
|
563 enforce_null_policy( x, "Null pointer in 'insert()'" );
|
Chris@16
|
564
|
Chris@16
|
565 auto_type ptr( x ); // nothrow
|
Chris@16
|
566 iterator res( c_.insert( before.base(), x ) ); // strong, commit
|
Chris@16
|
567 ptr.release(); // nothrow
|
Chris@16
|
568 return res;
|
Chris@16
|
569 }
|
Chris@16
|
570
|
Chris@16
|
571 template< class U >
|
Chris@16
|
572 iterator insert( iterator before, std::auto_ptr<U> x )
|
Chris@16
|
573 {
|
Chris@16
|
574 return insert( before, x.release() );
|
Chris@16
|
575 }
|
Chris@16
|
576
|
Chris@16
|
577 iterator erase( iterator x ) // nothrow
|
Chris@16
|
578 {
|
Chris@16
|
579 BOOST_ASSERT( !empty() );
|
Chris@16
|
580 BOOST_ASSERT( x != end() );
|
Chris@16
|
581
|
Chris@16
|
582 remove( x );
|
Chris@16
|
583 return iterator( c_.erase( x.base() ) );
|
Chris@16
|
584 }
|
Chris@16
|
585
|
Chris@16
|
586 iterator erase( iterator first, iterator last ) // nothrow
|
Chris@16
|
587 {
|
Chris@16
|
588 remove( first, last );
|
Chris@16
|
589 return iterator( c_.erase( first.base(),
|
Chris@16
|
590 last.base() ) );
|
Chris@16
|
591 }
|
Chris@16
|
592
|
Chris@16
|
593 template< class Range >
|
Chris@16
|
594 iterator erase( const Range& r )
|
Chris@16
|
595 {
|
Chris@16
|
596 return erase( boost::begin(r), boost::end(r) );
|
Chris@16
|
597 }
|
Chris@16
|
598
|
Chris@16
|
599 void clear()
|
Chris@16
|
600 {
|
Chris@16
|
601 remove_all();
|
Chris@16
|
602 c_.clear();
|
Chris@16
|
603 }
|
Chris@16
|
604
|
Chris@16
|
605 public: // access interface
|
Chris@16
|
606
|
Chris@16
|
607 auto_type release( iterator where )
|
Chris@16
|
608 {
|
Chris@16
|
609 BOOST_ASSERT( where != end() );
|
Chris@16
|
610
|
Chris@16
|
611 BOOST_PTR_CONTAINER_THROW_EXCEPTION( empty(), bad_ptr_container_operation,
|
Chris@16
|
612 "'release()' on empty container" );
|
Chris@16
|
613
|
Chris@16
|
614 auto_type ptr( Config::get_pointer( where ) ); // nothrow
|
Chris@16
|
615 c_.erase( where.base() ); // nothrow
|
Chris@16
|
616 return boost::ptr_container_detail::move( ptr );
|
Chris@16
|
617 }
|
Chris@16
|
618
|
Chris@16
|
619 auto_type replace( iterator where, Ty_* x ) // strong
|
Chris@16
|
620 {
|
Chris@16
|
621 BOOST_ASSERT( where != end() );
|
Chris@16
|
622
|
Chris@16
|
623 enforce_null_policy( x, "Null pointer in 'replace()'" );
|
Chris@16
|
624
|
Chris@16
|
625 auto_type ptr( x );
|
Chris@16
|
626
|
Chris@16
|
627 BOOST_PTR_CONTAINER_THROW_EXCEPTION( empty(), bad_ptr_container_operation,
|
Chris@16
|
628 "'replace()' on empty container" );
|
Chris@16
|
629
|
Chris@16
|
630 auto_type old( Config::get_pointer( where ) ); // nothrow
|
Chris@16
|
631 const_cast<void*&>(*where.base()) = ptr.release();
|
Chris@16
|
632 return boost::ptr_container_detail::move( old );
|
Chris@16
|
633 }
|
Chris@16
|
634
|
Chris@16
|
635 template< class U >
|
Chris@16
|
636 auto_type replace( iterator where, std::auto_ptr<U> x )
|
Chris@16
|
637 {
|
Chris@16
|
638 return replace( where, x.release() );
|
Chris@16
|
639 }
|
Chris@16
|
640
|
Chris@16
|
641 auto_type replace( size_type idx, Ty_* x ) // strong
|
Chris@16
|
642 {
|
Chris@16
|
643 enforce_null_policy( x, "Null pointer in 'replace()'" );
|
Chris@16
|
644
|
Chris@16
|
645 auto_type ptr( x );
|
Chris@16
|
646
|
Chris@16
|
647 BOOST_PTR_CONTAINER_THROW_EXCEPTION( idx >= size(), bad_index,
|
Chris@16
|
648 "'replace()' out of bounds" );
|
Chris@16
|
649
|
Chris@16
|
650 auto_type old( static_cast<Ty_*>( c_[idx] ) ); // nothrow
|
Chris@16
|
651 c_[idx] = ptr.release(); // nothrow, commit
|
Chris@16
|
652 return boost::ptr_container_detail::move( old );
|
Chris@16
|
653 }
|
Chris@16
|
654
|
Chris@16
|
655 template< class U >
|
Chris@16
|
656 auto_type replace( size_type idx, std::auto_ptr<U> x )
|
Chris@16
|
657 {
|
Chris@16
|
658 return replace( idx, x.release() );
|
Chris@16
|
659 }
|
Chris@16
|
660
|
Chris@16
|
661 }; // 'reversible_ptr_container'
|
Chris@16
|
662
|
Chris@16
|
663
|
Chris@16
|
664 #if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
|
Chris@16
|
665 #define BOOST_PTR_CONTAINER_DEFINE_RELEASE( base_type ) \
|
Chris@16
|
666 typename base_type::auto_type \
|
Chris@16
|
667 release( typename base_type::iterator i ) \
|
Chris@16
|
668 { \
|
Chris@16
|
669 return boost::ptr_container_detail::move(base_type::release(i)); \
|
Chris@16
|
670 }
|
Chris@16
|
671 #else
|
Chris@16
|
672 #define BOOST_PTR_CONTAINER_DEFINE_RELEASE( base_type ) \
|
Chris@16
|
673 using base_type::release;
|
Chris@16
|
674 #endif
|
Chris@16
|
675
|
Chris@16
|
676 //
|
Chris@16
|
677 // two-phase lookup of template functions
|
Chris@16
|
678 // is buggy on most compilers, so we use a macro instead
|
Chris@16
|
679 //
|
Chris@16
|
680 #define BOOST_PTR_CONTAINER_DEFINE_RELEASE_AND_CLONE( PC, base_type, this_type ) \
|
Chris@16
|
681 explicit PC( std::auto_ptr<this_type> r ) \
|
Chris@16
|
682 : base_type ( r ) { } \
|
Chris@16
|
683 \
|
Chris@16
|
684 PC& operator=( std::auto_ptr<this_type> r ) \
|
Chris@16
|
685 { \
|
Chris@16
|
686 base_type::operator=( r ); \
|
Chris@16
|
687 return *this; \
|
Chris@16
|
688 } \
|
Chris@16
|
689 \
|
Chris@16
|
690 std::auto_ptr<this_type> release() \
|
Chris@16
|
691 { \
|
Chris@16
|
692 std::auto_ptr<this_type> ptr( new this_type );\
|
Chris@16
|
693 this->swap( *ptr ); \
|
Chris@16
|
694 return ptr; \
|
Chris@16
|
695 } \
|
Chris@16
|
696 BOOST_PTR_CONTAINER_DEFINE_RELEASE( base_type ) \
|
Chris@16
|
697 \
|
Chris@16
|
698 std::auto_ptr<this_type> clone() const \
|
Chris@16
|
699 { \
|
Chris@16
|
700 return std::auto_ptr<this_type>( new this_type( this->begin(), this->end() ) ); \
|
Chris@16
|
701 }
|
Chris@16
|
702
|
Chris@16
|
703 #define BOOST_PTR_CONTAINER_DEFINE_COPY_CONSTRUCTORS( PC, base_type ) \
|
Chris@16
|
704 \
|
Chris@16
|
705 template< class U > \
|
Chris@16
|
706 PC( const PC<U>& r ) : base_type( r ) { } \
|
Chris@16
|
707 \
|
Chris@16
|
708 PC& operator=( PC r ) \
|
Chris@16
|
709 { \
|
Chris@16
|
710 this->swap( r ); \
|
Chris@16
|
711 return *this; \
|
Chris@16
|
712 } \
|
Chris@16
|
713
|
Chris@16
|
714
|
Chris@16
|
715 #define BOOST_PTR_CONTAINER_DEFINE_CONSTRUCTORS( PC, base_type ) \
|
Chris@16
|
716 typedef BOOST_DEDUCED_TYPENAME base_type::iterator iterator; \
|
Chris@16
|
717 typedef BOOST_DEDUCED_TYPENAME base_type::size_type size_type; \
|
Chris@16
|
718 typedef BOOST_DEDUCED_TYPENAME base_type::const_reference const_reference; \
|
Chris@16
|
719 typedef BOOST_DEDUCED_TYPENAME base_type::allocator_type allocator_type; \
|
Chris@16
|
720 PC() {} \
|
Chris@16
|
721 explicit PC( const allocator_type& a ) : base_type(a) {} \
|
Chris@16
|
722 template< class InputIterator > \
|
Chris@16
|
723 PC( InputIterator first, InputIterator last ) : base_type( first, last ) {} \
|
Chris@16
|
724 template< class InputIterator > \
|
Chris@16
|
725 PC( InputIterator first, InputIterator last, \
|
Chris@16
|
726 const allocator_type& a ) : base_type( first, last, a ) {}
|
Chris@16
|
727
|
Chris@16
|
728 #define BOOST_PTR_CONTAINER_DEFINE_NON_INHERITED_MEMBERS( PC, base_type, this_type ) \
|
Chris@16
|
729 BOOST_PTR_CONTAINER_DEFINE_CONSTRUCTORS( PC, base_type ) \
|
Chris@16
|
730 BOOST_PTR_CONTAINER_DEFINE_RELEASE_AND_CLONE( PC, base_type, this_type )
|
Chris@16
|
731
|
Chris@16
|
732 #define BOOST_PTR_CONTAINER_DEFINE_SEQEUENCE_MEMBERS( PC, base_type, this_type ) \
|
Chris@16
|
733 BOOST_PTR_CONTAINER_DEFINE_NON_INHERITED_MEMBERS( PC, base_type, this_type ) \
|
Chris@16
|
734 BOOST_PTR_CONTAINER_DEFINE_COPY_CONSTRUCTORS( PC, base_type )
|
Chris@16
|
735
|
Chris@16
|
736 } // namespace 'ptr_container_detail'
|
Chris@16
|
737
|
Chris@16
|
738 //
|
Chris@16
|
739 // @remark: expose movability of internal move-pointer
|
Chris@16
|
740 //
|
Chris@16
|
741 namespace ptr_container
|
Chris@16
|
742 {
|
Chris@16
|
743 using ptr_container_detail::move;
|
Chris@16
|
744 }
|
Chris@16
|
745
|
Chris@16
|
746 } // namespace 'boost'
|
Chris@16
|
747
|
Chris@16
|
748 #if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
|
Chris@16
|
749 #pragma warning(pop)
|
Chris@16
|
750 #endif
|
Chris@16
|
751
|
Chris@16
|
752 #endif
|