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_SEQUENCE_ADAPTER_HPP 13 #define BOOST_PTR_CONTAINER_PTR_SEQUENCE_ADAPTER_HPP 14 15 #if defined(_MSC_VER) && (_MSC_VER >= 1200) 16 # pragma once 17 #endif 18 19 20 #include <boost/ptr_container/detail/reversible_ptr_container.hpp> 21 #include <boost/ptr_container/indirect_fun.hpp> 22 #include <boost/ptr_container/detail/void_ptr_iterator.hpp> 23 #include <boost/ptr_container/detail/ptr_container_disable_deprecated.hpp> 24 #include <boost/type_traits/remove_pointer.hpp> 25 #include <boost/type_traits/is_same.hpp> 26 #include <boost/next_prior.hpp> 27 28 #if defined(BOOST_PTR_CONTAINER_DISABLE_DEPRECATED) 29 #pragma GCC diagnostic push 30 #pragma GCC diagnostic ignored "-Wdeprecated-declarations" 31 #endif 32 33 namespace boost 34 { 35 namespace ptr_container_detail 36 { 37 template 38 < 39 class T, 40 class VoidPtrSeq 41 > 42 struct sequence_config 43 { 44 typedef BOOST_DEDUCED_TYPENAME remove_nullable<T>::type 45 U; 46 typedef VoidPtrSeq 47 void_container_type; 48 49 typedef BOOST_DEDUCED_TYPENAME VoidPtrSeq::allocator_type 50 allocator_type; 51 52 typedef U value_type; 53 54 typedef void_ptr_iterator< 55 BOOST_DEDUCED_TYPENAME VoidPtrSeq::iterator, U > 56 iterator; 57 58 typedef void_ptr_iterator< 59 BOOST_DEDUCED_TYPENAME VoidPtrSeq::const_iterator, const U > 60 const_iterator; 61 62 #if defined(BOOST_NO_SFINAE) || defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING) 63 64 template< class Iter > get_pointerboost::ptr_container_detail::sequence_config65 static U* get_pointer( Iter i ) 66 { 67 return static_cast<U*>( *i.base() ); 68 } 69 70 #else 71 template< class Iter > get_pointerboost::ptr_container_detail::sequence_config72 static U* get_pointer( void_ptr_iterator<Iter,U> i ) 73 { 74 return static_cast<U*>( *i.base() ); 75 } 76 77 template< class Iter > get_pointerboost::ptr_container_detail::sequence_config78 static U* get_pointer( Iter i ) 79 { 80 return &*i; 81 } 82 #endif 83 84 #if defined(BOOST_NO_SFINAE) && !BOOST_WORKAROUND(__MWERKS__, <= 0x3003) 85 86 template< class Iter > get_const_pointerboost::ptr_container_detail::sequence_config87 static const U* get_const_pointer( Iter i ) 88 { 89 return static_cast<const U*>( *i.base() ); 90 } 91 92 #else // BOOST_NO_SFINAE 93 94 #if BOOST_WORKAROUND(__MWERKS__, <= 0x3003) 95 template< class Iter > get_const_pointerboost::ptr_container_detail::sequence_config96 static const U* get_const_pointer( void_ptr_iterator<Iter,U> i ) 97 { 98 return static_cast<const U*>( *i.base() ); 99 } 100 #else // BOOST_WORKAROUND 101 template< class Iter > get_const_pointerboost::ptr_container_detail::sequence_config102 static const U* get_const_pointer( void_ptr_iterator<Iter,const U> i ) 103 { 104 return static_cast<const U*>( *i.base() ); 105 } 106 #endif // BOOST_WORKAROUND 107 108 template< class Iter > get_const_pointerboost::ptr_container_detail::sequence_config109 static const U* get_const_pointer( Iter i ) 110 { 111 return &*i; 112 } 113 #endif // BOOST_NO_SFINAE 114 115 BOOST_STATIC_CONSTANT(bool, allow_null = boost::is_nullable<T>::value ); 116 }; 117 118 } // ptr_container_detail 119 120 121 template< class Iterator, class T > is_null(void_ptr_iterator<Iterator,T> i)122 inline bool is_null( void_ptr_iterator<Iterator,T> i ) 123 { 124 return *i.base() == 0; 125 } 126 127 128 129 template 130 < 131 class T, 132 class VoidPtrSeq, 133 class CloneAllocator = heap_clone_allocator 134 > 135 class ptr_sequence_adapter : public 136 ptr_container_detail::reversible_ptr_container< ptr_container_detail::sequence_config<T,VoidPtrSeq>, 137 CloneAllocator > 138 { 139 typedef ptr_container_detail::reversible_ptr_container< ptr_container_detail::sequence_config<T,VoidPtrSeq>, 140 CloneAllocator > 141 base_type; 142 143 typedef ptr_sequence_adapter<T,VoidPtrSeq,CloneAllocator> 144 this_type; 145 146 protected: 147 typedef BOOST_DEDUCED_TYPENAME base_type::scoped_deleter scoped_deleter; 148 149 public: 150 typedef BOOST_DEDUCED_TYPENAME base_type::value_type value_type; 151 typedef BOOST_DEDUCED_TYPENAME base_type::reference reference; 152 typedef BOOST_DEDUCED_TYPENAME base_type::const_reference 153 const_reference; 154 typedef BOOST_DEDUCED_TYPENAME base_type::auto_type auto_type; 155 typedef BOOST_DEDUCED_TYPENAME base_type::clone_allocator_type 156 clone_allocator_type; 157 typedef BOOST_DEDUCED_TYPENAME base_type::iterator iterator; 158 typedef BOOST_DEDUCED_TYPENAME base_type::size_type size_type; 159 typedef BOOST_DEDUCED_TYPENAME base_type::allocator_type 160 allocator_type; 161 ptr_sequence_adapter()162 ptr_sequence_adapter() 163 { } 164 165 template< class Allocator > ptr_sequence_adapter(const Allocator & a)166 explicit ptr_sequence_adapter( const Allocator& a ) 167 : base_type( a ) 168 { } 169 170 template< class SizeType > ptr_sequence_adapter(SizeType n,ptr_container_detail::fixed_length_sequence_tag tag)171 ptr_sequence_adapter( SizeType n, 172 ptr_container_detail::fixed_length_sequence_tag tag ) 173 : base_type( n, tag ) 174 { } 175 176 template< class SizeType, class Allocator > ptr_sequence_adapter(SizeType n,const Allocator & a,ptr_container_detail::fixed_length_sequence_tag tag)177 ptr_sequence_adapter( SizeType n, const Allocator& a, 178 ptr_container_detail::fixed_length_sequence_tag tag ) 179 : base_type( n, a, tag ) 180 { } 181 182 template< class InputIterator > ptr_sequence_adapter(InputIterator first,InputIterator last)183 ptr_sequence_adapter( InputIterator first, InputIterator last ) 184 : base_type( first, last ) 185 { } 186 187 template< class InputIterator, class Allocator > ptr_sequence_adapter(InputIterator first,InputIterator last,const Allocator & a)188 ptr_sequence_adapter( InputIterator first, InputIterator last, 189 const Allocator& a ) 190 : base_type( first, last, a ) 191 { } 192 193 template< class ForwardIterator > ptr_sequence_adapter(ForwardIterator first,ForwardIterator last,ptr_container_detail::fixed_length_sequence_tag tag)194 ptr_sequence_adapter( ForwardIterator first, 195 ForwardIterator last, 196 ptr_container_detail::fixed_length_sequence_tag tag ) 197 : base_type( first, last, tag ) 198 { } 199 200 template< class SizeType, class ForwardIterator > ptr_sequence_adapter(SizeType n,ForwardIterator first,ForwardIterator last,ptr_container_detail::fixed_length_sequence_tag tag)201 ptr_sequence_adapter( SizeType n, 202 ForwardIterator first, 203 ForwardIterator last, 204 ptr_container_detail::fixed_length_sequence_tag tag ) 205 : base_type( n, first, last, tag ) 206 { } 207 ptr_sequence_adapter(const ptr_sequence_adapter & r)208 ptr_sequence_adapter( const ptr_sequence_adapter& r ) 209 : base_type( r ) 210 { } 211 212 template< class U > ptr_sequence_adapter(const ptr_sequence_adapter<U,VoidPtrSeq,CloneAllocator> & r)213 ptr_sequence_adapter( const ptr_sequence_adapter<U,VoidPtrSeq,CloneAllocator>& r ) 214 : base_type( r ) 215 { } 216 ptr_sequence_adapter(const ptr_sequence_adapter & r,ptr_container_detail::fixed_length_sequence_tag tag)217 ptr_sequence_adapter( const ptr_sequence_adapter& r, 218 ptr_container_detail::fixed_length_sequence_tag tag ) 219 : base_type( r, tag ) 220 { } 221 222 template< class U > ptr_sequence_adapter(const ptr_sequence_adapter<U,VoidPtrSeq,CloneAllocator> & r,ptr_container_detail::fixed_length_sequence_tag tag)223 ptr_sequence_adapter( const ptr_sequence_adapter<U,VoidPtrSeq,CloneAllocator>& r, 224 ptr_container_detail::fixed_length_sequence_tag tag ) 225 : base_type( r, tag ) 226 { } 227 228 #ifndef BOOST_NO_AUTO_PTR 229 template< class PtrContainer > ptr_sequence_adapter(std::auto_ptr<PtrContainer> clone)230 explicit ptr_sequence_adapter( std::auto_ptr<PtrContainer> clone ) 231 : base_type( clone ) 232 { } 233 #endif 234 #ifndef BOOST_NO_CXX11_SMART_PTR 235 template< class PtrContainer > ptr_sequence_adapter(std::unique_ptr<PtrContainer> clone)236 explicit ptr_sequence_adapter( std::unique_ptr<PtrContainer> clone ) 237 : base_type( std::move( clone ) ) 238 { } 239 #endif 240 operator =(const ptr_sequence_adapter r)241 ptr_sequence_adapter& operator=( const ptr_sequence_adapter r ) 242 { 243 this->swap( r ); 244 return *this; 245 } 246 247 #ifndef BOOST_NO_AUTO_PTR 248 template< class PtrContainer > operator =(std::auto_ptr<PtrContainer> clone)249 ptr_sequence_adapter& operator=( std::auto_ptr<PtrContainer> clone ) 250 { 251 base_type::operator=( clone ); 252 return *this; 253 } 254 #endif 255 #ifndef BOOST_NO_CXX11_SMART_PTR 256 template< class PtrContainer > operator =(std::unique_ptr<PtrContainer> clone)257 ptr_sequence_adapter& operator=( std::unique_ptr<PtrContainer> clone ) 258 { 259 base_type::operator=( std::move( clone ) ); 260 return *this; 261 } 262 #endif 263 264 ///////////////////////////////////////////////////////////// 265 // modifiers 266 ///////////////////////////////////////////////////////////// 267 push_back(value_type x)268 void push_back( value_type x ) // strong 269 { 270 this->enforce_null_policy( x, "Null pointer in 'push_back()'" ); 271 auto_type ptr( x, *this ); // notrow 272 this->base().push_back( x ); // strong, commit 273 ptr.release(); // nothrow 274 } 275 276 #ifndef BOOST_NO_AUTO_PTR 277 template< class U > push_back(std::auto_ptr<U> x)278 void push_back( std::auto_ptr<U> x ) 279 { 280 push_back( x.release() ); 281 } 282 #endif 283 #ifndef BOOST_NO_CXX11_SMART_PTR 284 template< class U > push_back(std::unique_ptr<U> x)285 void push_back( std::unique_ptr<U> x ) 286 { 287 push_back( x.release() ); 288 } 289 #endif 290 push_front(value_type x)291 void push_front( value_type x ) 292 { 293 this->enforce_null_policy( x, "Null pointer in 'push_front()'" ); 294 auto_type ptr( x, *this ); // nothrow 295 this->base().push_front( x ); // strong, commit 296 ptr.release(); // nothrow 297 } 298 299 #ifndef BOOST_NO_AUTO_PTR 300 template< class U > push_front(std::auto_ptr<U> x)301 void push_front( std::auto_ptr<U> x ) 302 { 303 push_front( x.release() ); 304 } 305 #endif 306 #ifndef BOOST_NO_CXX11_SMART_PTR 307 template< class U > push_front(std::unique_ptr<U> x)308 void push_front( std::unique_ptr<U> x ) 309 { 310 push_front( x.release() ); 311 } 312 #endif 313 pop_back()314 auto_type pop_back() 315 { 316 BOOST_ASSERT( !this->empty() && 317 "'pop_back()' on empty container" ); 318 auto_type ptr( static_cast<value_type>(this->base().back()), *this ); 319 // nothrow 320 this->base().pop_back(); // nothrow 321 return ptr_container_detail::move( ptr ); // nothrow 322 } 323 pop_front()324 auto_type pop_front() 325 { 326 BOOST_ASSERT( !this->empty() && 327 "'pop_front()' on empty container" ); 328 auto_type ptr( static_cast<value_type>(this->base().front()), *this ); 329 // nothrow 330 this->base().pop_front(); // nothrow 331 return ptr_container_detail::move( ptr ); 332 } 333 front()334 reference front() 335 { 336 BOOST_ASSERT( !this->empty() && 337 "accessing 'front()' on empty container" ); 338 339 BOOST_ASSERT( !::boost::is_null( this->begin() ) ); 340 return *this->begin(); 341 } 342 front() const343 const_reference front() const 344 { 345 return const_cast<ptr_sequence_adapter*>(this)->front(); 346 } 347 back()348 reference back() 349 { 350 BOOST_ASSERT( !this->empty() && 351 "accessing 'back()' on empty container" ); 352 BOOST_ASSERT( !::boost::is_null( --this->end() ) ); 353 return *--this->end(); 354 } 355 back() const356 const_reference back() const 357 { 358 return const_cast<ptr_sequence_adapter*>(this)->back(); 359 } 360 361 public: // deque/vector inerface 362 operator [](size_type n)363 reference operator[]( size_type n ) // nothrow 364 { 365 BOOST_ASSERT( n < this->size() ); 366 BOOST_ASSERT( !this->is_null( n ) ); 367 return *static_cast<value_type>( this->base()[n] ); 368 } 369 operator [](size_type n) const370 const_reference operator[]( size_type n ) const // nothrow 371 { 372 BOOST_ASSERT( n < this->size() ); 373 BOOST_ASSERT( !this->is_null( n ) ); 374 return *static_cast<value_type>( this->base()[n] ); 375 } 376 at(size_type n)377 reference at( size_type n ) 378 { 379 BOOST_PTR_CONTAINER_THROW_EXCEPTION( n >= this->size(), bad_index, 380 "'at()' out of bounds" ); 381 BOOST_ASSERT( !this->is_null( n ) ); 382 return (*this)[n]; 383 } 384 at(size_type n) const385 const_reference at( size_type n ) const 386 { 387 BOOST_PTR_CONTAINER_THROW_EXCEPTION( n >= this->size(), bad_index, 388 "'at()' out of bounds" ); 389 BOOST_ASSERT( !this->is_null( n ) ); 390 return (*this)[n]; 391 } 392 393 public: // vector interface 394 capacity() const395 size_type capacity() const 396 { 397 return this->base().capacity(); 398 } 399 reserve(size_type n)400 void reserve( size_type n ) 401 { 402 this->base().reserve( n ); 403 } 404 reverse()405 void reverse() 406 { 407 this->base().reverse(); 408 } 409 410 public: // assign, insert, transfer 411 412 // overhead: 1 heap allocation (very cheap compared to cloning) 413 template< class InputIterator > assign(InputIterator first,InputIterator last)414 void assign( InputIterator first, InputIterator last ) // strong 415 { 416 base_type temp( first, last ); 417 this->swap( temp ); 418 } 419 420 template< class Range > assign(const Range & r)421 void assign( const Range& r ) // strong 422 { 423 assign( boost::begin(r), boost::end(r ) ); 424 } 425 426 private: 427 template< class I > insert_impl(iterator before,I first,I last,std::input_iterator_tag)428 void insert_impl( iterator before, I first, I last, std::input_iterator_tag ) // strong 429 { 430 ptr_sequence_adapter temp(first,last); // strong 431 transfer( before, temp ); // strong, commit 432 } 433 434 template< class I > insert_impl(iterator before,I first,I last,std::forward_iterator_tag)435 void insert_impl( iterator before, I first, I last, std::forward_iterator_tag ) // strong 436 { 437 if( first == last ) 438 return; 439 scoped_deleter sd( *this, first, last ); // strong 440 this->insert_clones_and_release( sd, before ); // strong, commit 441 } 442 443 public: 444 445 using base_type::insert; 446 447 template< class InputIterator > insert(iterator before,InputIterator first,InputIterator last)448 void insert( iterator before, InputIterator first, InputIterator last ) // strong 449 { 450 insert_impl( before, first, last, BOOST_DEDUCED_TYPENAME 451 iterator_category<InputIterator>::type() ); 452 } 453 454 #if defined(BOOST_NO_SFINAE) || defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING) 455 #else 456 template< class Range > 457 BOOST_DEDUCED_TYPENAME 458 boost::disable_if< ptr_container_detail::is_pointer_or_integral<Range> >::type insert(iterator before,const Range & r)459 insert( iterator before, const Range& r ) 460 { 461 insert( before, boost::begin(r), boost::end(r) ); 462 } 463 464 #endif 465 466 template< class PtrSeqAdapter > transfer(iterator before,BOOST_DEDUCED_TYPENAME PtrSeqAdapter::iterator first,BOOST_DEDUCED_TYPENAME PtrSeqAdapter::iterator last,PtrSeqAdapter & from)467 void transfer( iterator before, 468 BOOST_DEDUCED_TYPENAME PtrSeqAdapter::iterator first, 469 BOOST_DEDUCED_TYPENAME PtrSeqAdapter::iterator last, 470 PtrSeqAdapter& from ) // strong 471 { 472 BOOST_ASSERT( (void*)&from != (void*)this ); 473 if( from.empty() ) 474 return; 475 this->base(). 476 insert( before.base(), first.base(), last.base() ); // strong 477 from.base().erase( first.base(), last.base() ); // nothrow 478 } 479 480 template< class PtrSeqAdapter > transfer(iterator before,BOOST_DEDUCED_TYPENAME PtrSeqAdapter::iterator object,PtrSeqAdapter & from)481 void transfer( iterator before, 482 BOOST_DEDUCED_TYPENAME PtrSeqAdapter::iterator object, 483 PtrSeqAdapter& from ) // strong 484 { 485 BOOST_ASSERT( (void*)&from != (void*)this ); 486 if( from.empty() ) 487 return; 488 this->base().insert( before.base(), *object.base() ); // strong 489 from.base().erase( object.base() ); // nothrow 490 } 491 492 #if defined(BOOST_NO_SFINAE) || defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING) 493 #else 494 495 template< class PtrSeqAdapter, class Range > 496 BOOST_DEDUCED_TYPENAME boost::disable_if< boost::is_same< Range, 497 BOOST_DEDUCED_TYPENAME PtrSeqAdapter::iterator > >::type transfer(iterator before,const Range & r,PtrSeqAdapter & from)498 transfer( iterator before, const Range& r, PtrSeqAdapter& from ) // strong 499 { 500 transfer( before, boost::begin(r), boost::end(r), from ); 501 } 502 503 #endif 504 template< class PtrSeqAdapter > transfer(iterator before,PtrSeqAdapter & from)505 void transfer( iterator before, PtrSeqAdapter& from ) // strong 506 { 507 BOOST_ASSERT( (void*)&from != (void*)this ); 508 if( from.empty() ) 509 return; 510 this->base(). 511 insert( before.base(), 512 from.begin().base(), from.end().base() ); // strong 513 from.base().clear(); // nothrow 514 } 515 516 public: // C-array support 517 transfer(iterator before,value_type * from,size_type size,bool delete_from=true)518 void transfer( iterator before, value_type* from, 519 size_type size, bool delete_from = true ) // strong 520 { 521 BOOST_ASSERT( from != 0 ); 522 if( delete_from ) 523 { 524 BOOST_DEDUCED_TYPENAME base_type::scoped_deleter 525 deleter( *this, from, size ); // nothrow 526 this->base().insert( before.base(), from, from + size ); // strong 527 deleter.release(); // nothrow 528 } 529 else 530 { 531 this->base().insert( before.base(), from, from + size ); // strong 532 } 533 } 534 c_array()535 value_type* c_array() // nothrow 536 { 537 if( this->empty() ) 538 return 0; 539 T** res = reinterpret_cast<T**>( &this->begin().base()[0] ); 540 return res; 541 } 542 543 public: // null functions 544 is_null(size_type idx) const545 bool is_null( size_type idx ) const 546 { 547 BOOST_ASSERT( idx < this->size() ); 548 return this->base()[idx] == 0; 549 } 550 551 public: // resize 552 resize(size_type size)553 void resize( size_type size ) // basic 554 { 555 size_type old_size = this->size(); 556 if( old_size > size ) 557 { 558 this->erase( boost::next( this->begin(), size ), this->end() ); 559 } 560 else if( size > old_size ) 561 { 562 for( ; old_size != size; ++old_size ) 563 this->push_back( new BOOST_DEDUCED_TYPENAME 564 boost::remove_pointer<value_type>::type() ); 565 } 566 567 BOOST_ASSERT( this->size() == size ); 568 } 569 resize(size_type size,value_type to_clone)570 void resize( size_type size, value_type to_clone ) // basic 571 { 572 size_type old_size = this->size(); 573 if( old_size > size ) 574 { 575 this->erase( boost::next( this->begin(), size ), this->end() ); 576 } 577 else if( size > old_size ) 578 { 579 for( ; old_size != size; ++old_size ) 580 this->push_back( this->null_policy_allocate_clone( to_clone ) ); 581 } 582 583 BOOST_ASSERT( this->size() == size ); 584 } 585 rresize(size_type size)586 void rresize( size_type size ) // basic 587 { 588 size_type old_size = this->size(); 589 if( old_size > size ) 590 { 591 this->erase( this->begin(), 592 boost::next( this->begin(), old_size - size ) ); 593 } 594 else if( size > old_size ) 595 { 596 for( ; old_size != size; ++old_size ) 597 this->push_front( new BOOST_DEDUCED_TYPENAME 598 boost::remove_pointer<value_type>::type() ); 599 } 600 601 BOOST_ASSERT( this->size() == size ); 602 } 603 rresize(size_type size,value_type to_clone)604 void rresize( size_type size, value_type to_clone ) // basic 605 { 606 size_type old_size = this->size(); 607 if( old_size > size ) 608 { 609 this->erase( this->begin(), 610 boost::next( this->begin(), old_size - size ) ); 611 } 612 else if( size > old_size ) 613 { 614 for( ; old_size != size; ++old_size ) 615 this->push_front( this->null_policy_allocate_clone( to_clone ) ); 616 } 617 618 BOOST_ASSERT( this->size() == size ); 619 } 620 621 public: // algorithms 622 sort(iterator first,iterator last)623 void sort( iterator first, iterator last ) 624 { 625 sort( first, last, std::less<T>() ); 626 } 627 sort()628 void sort() 629 { 630 sort( this->begin(), this->end() ); 631 } 632 633 template< class Compare > sort(iterator first,iterator last,Compare comp)634 void sort( iterator first, iterator last, Compare comp ) 635 { 636 BOOST_ASSERT( first <= last && "out of range sort()" ); 637 BOOST_ASSERT( this->begin() <= first && "out of range sort()" ); 638 BOOST_ASSERT( last <= this->end() && "out of range sort()" ); 639 // some static assert on the arguments of the comparison 640 std::sort( first.base(), last.base(), 641 void_ptr_indirect_fun<Compare,T>(comp) ); 642 } 643 644 template< class Compare > sort(Compare comp)645 void sort( Compare comp ) 646 { 647 sort( this->begin(), this->end(), comp ); 648 } 649 unique(iterator first,iterator last)650 void unique( iterator first, iterator last ) 651 { 652 unique( first, last, std::equal_to<T>() ); 653 } 654 unique()655 void unique() 656 { 657 unique( this->begin(), this->end() ); 658 } 659 660 private: 661 struct is_not_zero_ptr 662 { 663 template< class U > operator ()boost::ptr_sequence_adapter::is_not_zero_ptr664 bool operator()( const U* r ) const 665 { 666 return r != 0; 667 } 668 }; 669 670 protected: 671 template< class Fun, class Arg1 > 672 class void_ptr_delete_if 673 { 674 Fun fun; 675 public: 676 void_ptr_delete_if()677 void_ptr_delete_if() : fun(Fun()) 678 { } 679 void_ptr_delete_if(Fun f)680 void_ptr_delete_if( Fun f ) : fun(f) 681 { } 682 operator ()(void * r) const683 bool operator()( void* r ) const 684 { 685 BOOST_ASSERT( r != 0 ); 686 Arg1 arg1 = static_cast<Arg1>(r); 687 if( fun( *arg1 ) ) 688 { 689 clone_allocator_type::deallocate_clone( arg1 ); 690 return true; 691 } 692 return false; 693 } 694 }; 695 696 private: compact_and_erase_nulls(iterator first,iterator last)697 void compact_and_erase_nulls( iterator first, iterator last ) // nothrow 698 { 699 typename base_type::ptr_iterator p = std::stable_partition( 700 first.base(), 701 last.base(), 702 is_not_zero_ptr() ); 703 this->base().erase( p, this->end().base() ); 704 705 } 706 range_check_impl(iterator,iterator,std::bidirectional_iterator_tag)707 void range_check_impl( iterator, iterator, 708 std::bidirectional_iterator_tag ) 709 { /* do nothing */ } 710 range_check_impl(iterator first,iterator last,std::random_access_iterator_tag)711 void range_check_impl( iterator first, iterator last, 712 std::random_access_iterator_tag ) 713 { 714 BOOST_ASSERT( first <= last && "out of range unique()/erase_if()" ); 715 BOOST_ASSERT( this->begin() <= first && "out of range unique()/erase_if()" ); 716 BOOST_ASSERT( last <= this->end() && "out of range unique()/erase_if)(" ); 717 } 718 range_check(iterator first,iterator last)719 void range_check( iterator first, iterator last ) 720 { 721 range_check_impl( first, last, 722 BOOST_DEDUCED_TYPENAME iterator_category<iterator>::type() ); 723 } 724 725 public: 726 727 template< class Compare > unique(iterator first,iterator last,Compare comp)728 void unique( iterator first, iterator last, Compare comp ) 729 { 730 range_check(first,last); 731 732 iterator prev = first; 733 iterator next = first; 734 ++next; 735 for( ; next != last; ++next ) 736 { 737 BOOST_ASSERT( !::boost::is_null(prev) ); 738 BOOST_ASSERT( !::boost::is_null(next) ); 739 if( comp( *prev, *next ) ) 740 { 741 this->remove( next ); // delete object 742 *next.base() = 0; // mark pointer as deleted 743 } 744 else 745 { 746 prev = next; 747 } 748 // ++next 749 } 750 751 compact_and_erase_nulls( first, last ); 752 } 753 754 template< class Compare > unique(Compare comp)755 void unique( Compare comp ) 756 { 757 unique( this->begin(), this->end(), comp ); 758 } 759 760 template< class Pred > erase_if(iterator first,iterator last,Pred pred)761 void erase_if( iterator first, iterator last, Pred pred ) 762 { 763 range_check(first,last); 764 this->base().erase( std::remove_if( first.base(), last.base(), 765 void_ptr_delete_if<Pred,value_type>(pred) ), 766 last.base() ); 767 } 768 769 template< class Pred > erase_if(Pred pred)770 void erase_if( Pred pred ) 771 { 772 erase_if( this->begin(), this->end(), pred ); 773 } 774 775 merge(iterator first,iterator last,ptr_sequence_adapter & from)776 void merge( iterator first, iterator last, 777 ptr_sequence_adapter& from ) 778 { 779 merge( first, last, from, std::less<T>() ); 780 } 781 782 template< class BinPred > merge(iterator first,iterator last,ptr_sequence_adapter & from,BinPred pred)783 void merge( iterator first, iterator last, 784 ptr_sequence_adapter& from, BinPred pred ) 785 { 786 void_ptr_indirect_fun<BinPred,T> bin_pred(pred); 787 size_type current_size = this->size(); 788 this->transfer( this->end(), first, last, from ); 789 typename base_type::ptr_iterator middle = this->begin().base(); 790 std::advance(middle,current_size); 791 std::inplace_merge( this->begin().base(), 792 middle, 793 this->end().base(), 794 bin_pred ); 795 } 796 merge(ptr_sequence_adapter & r)797 void merge( ptr_sequence_adapter& r ) 798 { 799 merge( r, std::less<T>() ); 800 BOOST_ASSERT( r.empty() ); 801 } 802 803 template< class BinPred > merge(ptr_sequence_adapter & r,BinPred pred)804 void merge( ptr_sequence_adapter& r, BinPred pred ) 805 { 806 merge( r.begin(), r.end(), r, pred ); 807 BOOST_ASSERT( r.empty() ); 808 } 809 810 }; 811 812 813 } // namespace 'boost' 814 815 #if defined(BOOST_PTR_CONTAINER_DISABLE_DEPRECATED) 816 #pragma GCC diagnostic pop 817 #endif 818 819 #endif 820