• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
13 #ifndef BOOST_PTR_CONTAINER_DETAIL_REVERSIBLE_PTR_CONTAINER_HPP
14 #define BOOST_PTR_CONTAINER_DETAIL_REVERSIBLE_PTR_CONTAINER_HPP
15 
16 #if defined(_MSC_VER) && (_MSC_VER >= 1200)
17 # pragma once
18 #endif
19 
20 #include <boost/ptr_container/detail/throw_exception.hpp>
21 #include <boost/ptr_container/detail/scoped_deleter.hpp>
22 #include <boost/ptr_container/detail/static_move_ptr.hpp>
23 #include <boost/ptr_container/detail/ptr_container_disable_deprecated.hpp>
24 #include <boost/ptr_container/exception.hpp>
25 #include <boost/ptr_container/clone_allocator.hpp>
26 #include <boost/ptr_container/nullable.hpp>
27 
28 #ifdef BOOST_NO_SFINAE
29 #else
30 #include <boost/range/functions.hpp>
31 #endif
32 
33 #include <boost/config.hpp>
34 #include <boost/iterator/reverse_iterator.hpp>
35 #include <boost/range/iterator.hpp>
36 #include <boost/utility/enable_if.hpp>
37 #include <boost/type_traits/is_pointer.hpp>
38 #include <boost/type_traits/is_integral.hpp>
39 #include <boost/swap.hpp>
40 #include <typeinfo>
41 #include <memory>
42 
43 #if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
44 #pragma warning(push)
45 #pragma warning(disable:4127)
46 #pragma warning(disable:4224) // formal parameter was previously defined as a type.
47 #endif
48 
49 #if defined(BOOST_PTR_CONTAINER_DISABLE_DEPRECATED)
50 #pragma GCC diagnostic push
51 #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
52 #endif
53 
54 namespace boost
55 {
56 
57 namespace ptr_container_detail
58 {
59     template< class Container >
60     struct dynamic_clone_deleter
61     {
dynamic_clone_deleterboost::ptr_container_detail::dynamic_clone_deleter62         dynamic_clone_deleter() { }
dynamic_clone_deleterboost::ptr_container_detail::dynamic_clone_deleter63         dynamic_clone_deleter( Container& cont ) : cont(&cont) { }
64         Container* cont;
65 
66         template< class T >
operator ()boost::ptr_container_detail::dynamic_clone_deleter67         void operator()( const T* p ) const
68         {
69             // remark: static_move_ptr already test for null
70             cont->get_clone_allocator().deallocate_clone( p );
71         }
72     };
73 
74     template< class CloneAllocator >
75     struct static_clone_deleter
76     {
static_clone_deleterboost::ptr_container_detail::static_clone_deleter77         static_clone_deleter() { }
78         template< class Dummy >
static_clone_deleterboost::ptr_container_detail::static_clone_deleter79         static_clone_deleter( const Dummy& ) { }
80 
81         template< class T >
operator ()boost::ptr_container_detail::static_clone_deleter82         void operator()( const T* p ) const
83         {
84             // remark: static_move_ptr already test for null
85             CloneAllocator::deallocate_clone( p );
86         }
87     };
88 
89     template< class T >
90     struct is_pointer_or_integral
91     {
92         BOOST_STATIC_CONSTANT(bool, value = is_pointer<T>::value || is_integral<T>::value );
93     };
94 
95     struct is_pointer_or_integral_tag {};
96     struct is_range_tag {};
97     struct sequence_tag {};
98     struct fixed_length_sequence_tag : sequence_tag {};
99     struct associative_container_tag {};
100     struct ordered_associative_container_tag : associative_container_tag {};
101     struct unordered_associative_container_tag : associative_container_tag {};
102 
103 
104 
105     template
106     <
107         class Config,
108         class CloneAllocator
109     >
110     class reversible_ptr_container : CloneAllocator
111     {
112     private:
113         BOOST_STATIC_CONSTANT( bool, allow_null = Config::allow_null );
114         BOOST_STATIC_CONSTANT( bool, is_clone_allocator_empty = sizeof(CloneAllocator) < sizeof(void*) );
115 
116         typedef BOOST_DEDUCED_TYPENAME Config::value_type Ty_;
117         typedef BOOST_DEDUCED_TYPENAME Config::void_container_type  container_type;
118         typedef dynamic_clone_deleter<reversible_ptr_container>     dynamic_deleter_type;
119         typedef static_clone_deleter<CloneAllocator>                static_deleter_type;
120 
121         container_type c_;
122 
123     public:
base()124         container_type&       base()               { return c_; }
125     protected: // having this public could break encapsulation
base() const126         const container_type& base() const         { return c_; }
127 
128     public: // typedefs
129         typedef  Ty_           object_type;
130         typedef  Ty_*          value_type;
131         typedef  Ty_*          pointer;
132         typedef  Ty_&          reference;
133         typedef  const Ty_&    const_reference;
134 
135         typedef  BOOST_DEDUCED_TYPENAME Config::iterator
136                                    iterator;
137         typedef  BOOST_DEDUCED_TYPENAME Config::const_iterator
138                                    const_iterator;
139         typedef  boost::reverse_iterator< iterator >
140                                    reverse_iterator;
141         typedef  boost::reverse_iterator< const_iterator >
142                                    const_reverse_iterator;
143         typedef  BOOST_DEDUCED_TYPENAME container_type::difference_type
144                                    difference_type;
145         typedef  BOOST_DEDUCED_TYPENAME container_type::size_type
146                                    size_type;
147         typedef  BOOST_DEDUCED_TYPENAME Config::allocator_type
148                                    allocator_type;
149         typedef CloneAllocator     clone_allocator_type;
150         typedef ptr_container_detail::static_move_ptr<Ty_,
151                      BOOST_DEDUCED_TYPENAME boost::mpl::if_c<is_clone_allocator_empty,
152                                                                 static_deleter_type,
153                                                                 dynamic_deleter_type>::type
154                                                      >
155                                    auto_type;
156 
157     protected:
158 
159         typedef ptr_container_detail::scoped_deleter<reversible_ptr_container>
160                                    scoped_deleter;
161         typedef BOOST_DEDUCED_TYPENAME container_type::iterator
162                                    ptr_iterator;
163         typedef BOOST_DEDUCED_TYPENAME container_type::const_iterator
164                                    ptr_const_iterator;
165     private:
166 
167         template< class InputIterator >
copy(InputIterator first,InputIterator last)168         void copy( InputIterator first, InputIterator last )
169         {
170             std::copy( first, last, begin() );
171         }
172 
copy(const reversible_ptr_container & r)173         void copy( const reversible_ptr_container& r )
174         {
175             this->copy( r.begin(), r.end() );
176         }
177 
copy_clones_and_release(scoped_deleter & sd)178         void copy_clones_and_release( scoped_deleter& sd ) // nothrow
179         {
180             BOOST_ASSERT( size_type( std::distance( sd.begin(), sd.end() ) ) == c_.size() );
181             std::copy( sd.begin(), sd.end(), c_.begin() );
182             sd.release();
183         }
184 
185         template< class ForwardIterator >
clone_assign(ForwardIterator first,ForwardIterator last)186         void clone_assign( ForwardIterator first,
187                            ForwardIterator last ) // strong
188         {
189             BOOST_ASSERT( first != last );
190             scoped_deleter sd( *this, first, last ); // strong
191             copy_clones_and_release( sd );           // nothrow
192         }
193 
194         template< class ForwardIterator >
clone_back_insert(ForwardIterator first,ForwardIterator last)195         void clone_back_insert( ForwardIterator first,
196                                 ForwardIterator last )
197         {
198             BOOST_ASSERT( first != last );
199             scoped_deleter sd( *this, first, last );
200             insert_clones_and_release( sd, end() );
201         }
202 
remove_all()203         void remove_all()
204         {
205             this->remove( begin(), end() );
206         }
207 
208     protected:
209 
insert_clones_and_release(scoped_deleter & sd,iterator where)210         void insert_clones_and_release( scoped_deleter& sd,
211                                         iterator where ) // strong
212         {
213             //
214             // 'c_.insert' always provides the strong guarantee for T* elements
215             // since a copy constructor of a pointer cannot throw
216             //
217             c_.insert( where.base(),
218                        sd.begin(), sd.end() );
219             sd.release();
220         }
221 
insert_clones_and_release(scoped_deleter & sd)222         void insert_clones_and_release( scoped_deleter& sd ) // strong
223         {
224             c_.insert( sd.begin(), sd.end() );
225             sd.release();
226         }
227 
228         template< class U >
remove(U * ptr)229         void remove( U* ptr )
230         {
231             this->deallocate_clone( ptr );
232         }
233 
234         template< class I >
remove(I i)235         void remove( I i )
236         {
237             this->deallocate_clone( Config::get_const_pointer(i) );
238         }
239 
240         template< class I >
remove(I first,I last)241         void remove( I first, I last )
242         {
243             for( ; first != last; ++first )
244                 this->remove( first );
245         }
246 
enforce_null_policy(const Ty_ * x,const char * msg)247         static void enforce_null_policy( const Ty_* x, const char* msg )
248         {
249             if( !allow_null )
250             {
251                 BOOST_PTR_CONTAINER_THROW_EXCEPTION( 0 == x && "null not allowed",
252                                                      bad_pointer, msg );
253             }
254         }
255 
256     public:
null_policy_allocate_clone(const Ty_ * x)257         Ty_* null_policy_allocate_clone( const Ty_* x )
258         {
259             if( allow_null )
260             {
261                 if( x == 0 )
262                     return 0;
263             }
264             else
265             {
266                 BOOST_ASSERT( x != 0 && "Cannot insert clone of null!" );
267             }
268 
269             Ty_* res = this->get_clone_allocator().allocate_clone( *x );
270             BOOST_ASSERT( typeid(*res) == typeid(*x) &&
271                           "CloneAllocator::allocate_clone() does not clone the "
272                           "object properly. Check that new_clone() is implemented"
273                           " correctly" );
274             return res;
275         }
276 
277         template< class Iterator >
null_policy_allocate_clone_from_iterator(Iterator i)278         Ty_* null_policy_allocate_clone_from_iterator( Iterator i )
279         {
280             return this->null_policy_allocate_clone(Config::get_const_pointer(i));
281         }
282 
null_policy_deallocate_clone(const Ty_ * x)283         void null_policy_deallocate_clone( const Ty_* x )
284         {
285             if( allow_null )
286             {
287                 if( x == 0 )
288                     return;
289             }
290 
291             this->get_clone_allocator().deallocate_clone( x );
292         }
293 
294     private:
295         template< class ForwardIterator >
advance(ForwardIterator begin,size_type n)296         ForwardIterator advance( ForwardIterator begin, size_type n )
297         {
298             ForwardIterator iter = begin;
299             std::advance( iter, n );
300             return iter;
301         }
302 
303         template< class I >
constructor_impl(I first,I last,std::input_iterator_tag)304         void constructor_impl( I first, I last, std::input_iterator_tag ) // basic
305         {
306             while( first != last )
307             {
308                 insert( end(), this->allocate_clone_from_iterator(first) );
309                 ++first;
310             }
311         }
312 
313         template< class I >
constructor_impl(I first,I last,std::forward_iterator_tag)314         void constructor_impl( I first, I last, std::forward_iterator_tag ) // strong
315         {
316             if( first == last )
317                 return;
318             clone_back_insert( first, last );
319         }
320 
321         template< class I >
associative_constructor_impl(I first,I last)322         void associative_constructor_impl( I first, I last ) // strong
323         {
324             if( first == last )
325                 return;
326 
327             scoped_deleter sd( *this, first, last );
328             insert_clones_and_release( sd );
329         }
330 
331     public: // foundation: should be protected, but public for poor compilers' sake.
reversible_ptr_container()332         reversible_ptr_container()
333         { }
334 
335         template< class SizeType >
reversible_ptr_container(SizeType n,unordered_associative_container_tag)336         reversible_ptr_container( SizeType n, unordered_associative_container_tag )
337           : c_( n )
338         { }
339 
340         template< class SizeType >
reversible_ptr_container(SizeType n,fixed_length_sequence_tag)341         reversible_ptr_container( SizeType n, fixed_length_sequence_tag )
342           : c_( n )
343         { }
344 
345         template< class SizeType >
reversible_ptr_container(SizeType n,const allocator_type & a,fixed_length_sequence_tag)346         reversible_ptr_container( SizeType n, const allocator_type& a,
347                                   fixed_length_sequence_tag )
348           : c_( n, a )
349         { }
350 
reversible_ptr_container(const allocator_type & a)351         explicit reversible_ptr_container( const allocator_type& a )
352          : c_( a )
353         { }
354 
355 #ifndef BOOST_NO_AUTO_PTR
356         template< class PtrContainer >
reversible_ptr_container(std::auto_ptr<PtrContainer> clone)357         explicit reversible_ptr_container( std::auto_ptr<PtrContainer> clone )
358         {
359             swap( *clone );
360         }
361 #endif
362 #ifndef BOOST_NO_CXX11_SMART_PTR
363         template< class PtrContainer >
reversible_ptr_container(std::unique_ptr<PtrContainer> clone)364         explicit reversible_ptr_container( std::unique_ptr<PtrContainer> clone )
365         {
366             swap( *clone );
367         }
368 #endif
369 
reversible_ptr_container(const reversible_ptr_container & r)370         reversible_ptr_container( const reversible_ptr_container& r )
371         {
372             constructor_impl( r.begin(), r.end(), std::forward_iterator_tag() );
373         }
374 
375         template< class C, class V >
reversible_ptr_container(const reversible_ptr_container<C,V> & r)376         reversible_ptr_container( const reversible_ptr_container<C,V>& r )
377         {
378             constructor_impl( r.begin(), r.end(), std::forward_iterator_tag() );
379         }
380 
381 #ifndef BOOST_NO_AUTO_PTR
382         template< class PtrContainer >
operator =(std::auto_ptr<PtrContainer> clone)383         reversible_ptr_container& operator=( std::auto_ptr<PtrContainer> clone ) // nothrow
384         {
385             swap( *clone );
386             return *this;
387         }
388 #endif
389 #ifndef BOOST_NO_CXX11_SMART_PTR
390         template< class PtrContainer >
operator =(std::unique_ptr<PtrContainer> clone)391         reversible_ptr_container& operator=( std::unique_ptr<PtrContainer> clone ) // nothrow
392         {
393             swap( *clone );
394             return *this;
395         }
396 #endif
397 
operator =(reversible_ptr_container r)398         reversible_ptr_container& operator=( reversible_ptr_container r ) // strong
399         {
400             swap( r );
401             return *this;
402         }
403 
404         // overhead: null-initilization of container pointer (very cheap compared to cloning)
405         // overhead: 1 heap allocation (very cheap compared to cloning)
406         template< class InputIterator >
reversible_ptr_container(InputIterator first,InputIterator last,const allocator_type & a=allocator_type ())407         reversible_ptr_container( InputIterator first,
408                                   InputIterator last,
409                                   const allocator_type& a = allocator_type() ) // basic, strong
410           : c_( a )
411         {
412             constructor_impl( first, last,
413 #if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
414 #else
415                               BOOST_DEDUCED_TYPENAME
416 #endif
417                               iterator_category<InputIterator>::type() );
418         }
419 
420         template< class Compare >
reversible_ptr_container(const Compare & comp,const allocator_type & a)421         reversible_ptr_container( const Compare& comp,
422                                   const allocator_type& a )
423           : c_( comp, a ) {}
424 
425         template< class ForwardIterator >
reversible_ptr_container(ForwardIterator first,ForwardIterator last,fixed_length_sequence_tag)426         reversible_ptr_container( ForwardIterator first,
427                                   ForwardIterator last,
428                                   fixed_length_sequence_tag )
429           : c_( std::distance(first,last) )
430         {
431             constructor_impl( first, last,
432                               std::forward_iterator_tag() );
433         }
434 
435         template< class SizeType, class InputIterator >
reversible_ptr_container(SizeType n,InputIterator first,InputIterator last,fixed_length_sequence_tag)436         reversible_ptr_container( SizeType n,
437                                   InputIterator first,
438                                   InputIterator last,
439                                   fixed_length_sequence_tag )
440           : c_( n )
441         {
442             constructor_impl( first, last,
443 #if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
444 #else
445                               BOOST_DEDUCED_TYPENAME
446 #endif
447                               iterator_category<InputIterator>::type() );
448         }
449 
450         template< class Compare >
reversible_ptr_container(const Compare & comp,const allocator_type & a,associative_container_tag)451         reversible_ptr_container( const Compare& comp,
452                                   const allocator_type& a,
453                                   associative_container_tag )
454           : c_( comp, a )
455         { }
456 
457         template< class InputIterator >
reversible_ptr_container(InputIterator first,InputIterator last,associative_container_tag)458         reversible_ptr_container( InputIterator first,
459                                   InputIterator last,
460                                   associative_container_tag )
461         {
462             associative_constructor_impl( first, last );
463         }
464 
465         template< class InputIterator, class Compare >
reversible_ptr_container(InputIterator first,InputIterator last,const Compare & comp,const allocator_type & a,associative_container_tag)466         reversible_ptr_container( InputIterator first,
467                                   InputIterator last,
468                                   const Compare& comp,
469                                   const allocator_type& a,
470                                   associative_container_tag )
471           : c_( comp, a )
472         {
473             associative_constructor_impl( first, last );
474         }
475 
reversible_ptr_container(size_type n)476         explicit reversible_ptr_container( size_type n )
477           : c_( n ) {}
478 
479         template< class Hash, class Pred >
reversible_ptr_container(const Hash & h,const Pred & pred,const allocator_type & a)480         reversible_ptr_container( const Hash& h,
481                                   const Pred& pred,
482                                   const allocator_type& a )
483           : c_( h, pred, a ) {}
484 
485         template< class InputIterator, class Hash, class Pred >
reversible_ptr_container(InputIterator first,InputIterator last,const Hash & h,const Pred & pred,const allocator_type & a)486         reversible_ptr_container( InputIterator first,
487                                   InputIterator last,
488                                   const Hash& h,
489                                   const Pred& pred,
490                                   const allocator_type& a )
491           : c_( h, pred, a )
492         {
493             associative_constructor_impl( first, last );
494         }
495 
496     public:
~reversible_ptr_container()497         ~reversible_ptr_container()
498         {
499             remove_all();
500         }
501 
502     public:
503 
get_allocator() const504         allocator_type get_allocator() const
505         {
506             return c_.get_allocator();
507         }
508 
get_clone_allocator()509         clone_allocator_type& get_clone_allocator()
510         {
511             return static_cast<clone_allocator_type&>(*this);
512         }
513 
get_clone_allocator() const514         const clone_allocator_type& get_clone_allocator() const
515         {
516             return static_cast<const clone_allocator_type&>(*this);
517         }
518 
519     public: // container requirements
begin()520         iterator begin()
521             { return iterator( c_.begin() ); }
begin() const522         const_iterator begin() const
523             { return const_iterator( c_.begin() ); }
end()524         iterator end()
525             { return iterator( c_.end() ); }
end() const526         const_iterator end() const
527             { return const_iterator( c_.end() ); }
528 
rbegin()529         reverse_iterator rbegin()
530             { return reverse_iterator( this->end() ); }
rbegin() const531         const_reverse_iterator rbegin() const
532             { return const_reverse_iterator( this->end() ); }
rend()533         reverse_iterator rend()
534             { return reverse_iterator( this->begin() ); }
rend() const535         const_reverse_iterator rend() const
536             { return const_reverse_iterator( this->begin() ); }
537 
cbegin() const538         const_iterator cbegin() const
539             { return const_iterator( c_.begin() ); }
cend() const540         const_iterator cend() const
541             { return const_iterator( c_.end() ); }
542 
crbegin() const543         const_reverse_iterator crbegin() const
544             { return const_reverse_iterator( this->end() ); }
crend() const545         const_reverse_iterator crend() const
546             { return const_reverse_iterator( this->begin() ); }
547 
swap(reversible_ptr_container & r)548         void swap( reversible_ptr_container& r ) // nothrow
549         {
550             boost::swap( get_clone_allocator(), r.get_clone_allocator() ); // nothrow
551             c_.swap( r.c_ ); // nothrow
552         }
553 
size() const554         size_type size() const // nothrow
555         {
556             return c_.size();
557         }
558 
max_size() const559         size_type max_size() const // nothrow
560         {
561             return c_.max_size();
562         }
563 
empty() const564         bool empty() const // nothrow
565         {
566             return c_.empty();
567         }
568 
569     public: // optional container requirements
570 
operator ==(const reversible_ptr_container & r) const571         bool operator==( const reversible_ptr_container& r ) const // nothrow
572         {
573             if( size() != r.size() )
574                 return false;
575             else
576                 return std::equal( begin(), end(), r.begin() );
577         }
578 
operator !=(const reversible_ptr_container & r) const579         bool operator!=( const reversible_ptr_container& r ) const // nothrow
580         {
581             return !(*this == r);
582         }
583 
operator <(const reversible_ptr_container & r) const584         bool operator<( const reversible_ptr_container& r ) const // nothrow
585         {
586              return std::lexicographical_compare( begin(), end(), r.begin(), r.end() );
587         }
588 
operator <=(const reversible_ptr_container & r) const589         bool operator<=( const reversible_ptr_container& r ) const // nothrow
590         {
591             return !(r < *this);
592         }
593 
operator >(const reversible_ptr_container & r) const594         bool operator>( const reversible_ptr_container& r ) const // nothrow
595         {
596             return r < *this;
597         }
598 
operator >=(const reversible_ptr_container & r) const599         bool operator>=( const reversible_ptr_container& r ) const // nothrow
600         {
601             return !(*this < r);
602         }
603 
604     public: // modifiers
605 
insert(iterator before,Ty_ * x)606         iterator insert( iterator before, Ty_* x )
607         {
608             enforce_null_policy( x, "Null pointer in 'insert()'" );
609 
610             auto_type ptr( x, *this );                     // nothrow
611             iterator res( c_.insert( before.base(), x ) ); // strong, commit
612             ptr.release();                                 // nothrow
613             return res;
614         }
615 
616 #ifndef BOOST_NO_AUTO_PTR
617         template< class U >
insert(iterator before,std::auto_ptr<U> x)618         iterator insert( iterator before, std::auto_ptr<U> x )
619         {
620             return insert( before, x.release() );
621         }
622 #endif
623 #ifndef BOOST_NO_CXX11_SMART_PTR
624         template< class U >
insert(iterator before,std::unique_ptr<U> x)625         iterator insert( iterator before, std::unique_ptr<U> x )
626         {
627             return insert( before, x.release() );
628         }
629 #endif
630 
erase(iterator x)631         iterator erase( iterator x ) // nothrow
632         {
633             BOOST_ASSERT( !empty() );
634             BOOST_ASSERT( x != end() );
635 
636             remove( x );
637             return iterator( c_.erase( x.base() ) );
638         }
639 
erase(iterator first,iterator last)640         iterator erase( iterator first, iterator last ) // nothrow
641         {
642             remove( first, last );
643             return iterator( c_.erase( first.base(),
644                                        last.base() ) );
645         }
646 
647         template< class Range >
erase(const Range & r)648         iterator erase( const Range& r )
649         {
650             return erase( boost::begin(r), boost::end(r) );
651         }
652 
clear()653         void clear()
654         {
655             remove_all();
656             c_.clear();
657         }
658 
659     public: // access interface
660 
release(iterator where)661         auto_type release( iterator where )
662         {
663             BOOST_ASSERT( where != end() );
664 
665             BOOST_PTR_CONTAINER_THROW_EXCEPTION( empty(), bad_ptr_container_operation,
666                                                  "'release()' on empty container" );
667 
668             auto_type ptr( Config::get_pointer(where), *this );  // nothrow
669             c_.erase( where.base() );                            // nothrow
670             return boost::ptr_container_detail::move( ptr );
671         }
672 
replace(iterator where,Ty_ * x)673         auto_type replace( iterator where, Ty_* x ) // strong
674         {
675             BOOST_ASSERT( where != end() );
676             enforce_null_policy( x, "Null pointer in 'replace()'" );
677 
678             auto_type ptr( x, *this );
679             BOOST_PTR_CONTAINER_THROW_EXCEPTION( empty(), bad_ptr_container_operation,
680                                                  "'replace()' on empty container" );
681 
682             auto_type old( Config::get_pointer(where), *this );  // nothrow
683             const_cast<void*&>(*where.base()) = ptr.release();
684             return boost::ptr_container_detail::move( old );
685         }
686 
687 #ifndef BOOST_NO_AUTO_PTR
688         template< class U >
replace(iterator where,std::auto_ptr<U> x)689         auto_type replace( iterator where, std::auto_ptr<U> x )
690         {
691             return replace( where, x.release() );
692         }
693 #endif
694 #ifndef BOOST_NO_CXX11_SMART_PTR
695         template< class U >
replace(iterator where,std::unique_ptr<U> x)696         auto_type replace( iterator where, std::unique_ptr<U> x )
697         {
698             return replace( where, x.release() );
699         }
700 #endif
701 
replace(size_type idx,Ty_ * x)702         auto_type replace( size_type idx, Ty_* x ) // strong
703         {
704             enforce_null_policy( x, "Null pointer in 'replace()'" );
705 
706             auto_type ptr( x, *this );
707             BOOST_PTR_CONTAINER_THROW_EXCEPTION( idx >= size(), bad_index,
708                                                  "'replace()' out of bounds" );
709 
710             auto_type old( static_cast<Ty_*>(c_[idx]), *this ); // nothrow
711             c_[idx] = ptr.release();                            // nothrow, commit
712             return boost::ptr_container_detail::move( old );
713         }
714 
715 #ifndef BOOST_NO_AUTO_PTR
716         template< class U >
replace(size_type idx,std::auto_ptr<U> x)717         auto_type replace( size_type idx, std::auto_ptr<U> x )
718         {
719             return replace( idx, x.release() );
720         }
721 #endif
722 #ifndef BOOST_NO_CXX11_SMART_PTR
723         template< class U >
replace(size_type idx,std::unique_ptr<U> x)724         auto_type replace( size_type idx, std::unique_ptr<U> x )
725         {
726             return replace( idx, x.release() );
727         }
728 #endif
729 
730     }; // 'reversible_ptr_container'
731 
732 
733 #if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
734 #define BOOST_PTR_CONTAINER_DEFINE_RELEASE( base_type ) \
735     typename base_type::auto_type                   \
736     release( typename base_type::iterator i )       \
737     {                                               \
738         return boost::ptr_container_detail::move(base_type::release(i)); \
739     }
740 #else
741 #define BOOST_PTR_CONTAINER_DEFINE_RELEASE( base_type ) \
742     using base_type::release;
743 #endif
744 
745 #ifndef BOOST_NO_AUTO_PTR
746 #define BOOST_PTR_CONTAINER_COPY_AND_ASSIGN_AUTO( PC, base_type, this_type ) \
747     explicit PC( std::auto_ptr<this_type> r )       \
748     : base_type ( r ) { }                           \
749                                                     \
750     PC& operator=( std::auto_ptr<this_type> r )     \
751     {                                               \
752         base_type::operator=( r );                  \
753         return *this;                               \
754     }
755 #else
756 #define BOOST_PTR_CONTAINER_COPY_AND_ASSIGN_AUTO( PC, base_type, this_type )
757 #endif
758 
759 #ifndef BOOST_NO_CXX11_SMART_PTR
760 #define BOOST_PTR_CONTAINER_COPY_AND_ASSIGN_UNIQUE( PC, base_type, this_type ) \
761     explicit PC( std::unique_ptr<this_type> r )     \
762     : base_type ( std::move( r ) ) { }              \
763                                                     \
764     PC& operator=( std::unique_ptr<this_type> r )   \
765     {                                               \
766         base_type::operator=( std::move( r ) );     \
767         return *this;                               \
768     }
769 #else
770 #define BOOST_PTR_CONTAINER_COPY_AND_ASSIGN_UNIQUE( PC, base_type, this_type )
771 #endif
772 
773 #ifndef BOOST_NO_AUTO_PTR
774 #define BOOST_PTR_CONTAINER_RELEASE_AND_CLONE( this_type ) \
775     std::auto_ptr<this_type> release()              \
776     {                                               \
777       std::auto_ptr<this_type> ptr( new this_type );\
778       this->swap( *ptr );                           \
779       return ptr;                                   \
780     }                                               \
781                                                     \
782     std::auto_ptr<this_type> clone() const          \
783     {                                               \
784        return std::auto_ptr<this_type>( new this_type( this->begin(), this->end() ) ); \
785     }
786 #elif !defined( BOOST_NO_CXX11_SMART_PTR )
787 #define BOOST_PTR_CONTAINER_RELEASE_AND_CLONE( this_type ) \
788     std::unique_ptr<this_type> release()              \
789     {                                                 \
790       std::unique_ptr<this_type> ptr( new this_type );\
791       this->swap( *ptr );                             \
792       return ptr;                                     \
793     }                                                 \
794                                                       \
795     std::unique_ptr<this_type> clone() const          \
796     {                                                 \
797        return std::unique_ptr<this_type>( new this_type( this->begin(), this->end() ) ); \
798     }
799 #else
800 #define BOOST_PTR_CONTAINER_RELEASE_AND_CLONE( this_type )
801 #endif
802 
803     //
804     // two-phase lookup of template functions
805     // is buggy on most compilers, so we use a macro instead
806     //
807 #define BOOST_PTR_CONTAINER_DEFINE_RELEASE_AND_CLONE( PC, base_type, this_type )  \
808     BOOST_PTR_CONTAINER_COPY_AND_ASSIGN_AUTO( PC, base_type, this_type )   \
809     BOOST_PTR_CONTAINER_COPY_AND_ASSIGN_UNIQUE( PC, base_type, this_type ) \
810     BOOST_PTR_CONTAINER_RELEASE_AND_CLONE( this_type )                     \
811     BOOST_PTR_CONTAINER_DEFINE_RELEASE( base_type )
812 
813 #define BOOST_PTR_CONTAINER_DEFINE_COPY_CONSTRUCTORS( PC, base_type ) \
814                                                                       \
815     template< class U >                                               \
816     PC( const PC<U>& r ) : base_type( r ) { }                         \
817                                                                       \
818     PC& operator=( PC r )                                             \
819     {                                                                 \
820         this->swap( r );                                              \
821         return *this;                                                 \
822     }                                                                 \
823 
824 
825 #define BOOST_PTR_CONTAINER_DEFINE_CONSTRUCTORS( PC, base_type )                       \
826     typedef BOOST_DEDUCED_TYPENAME base_type::iterator        iterator;                \
827     typedef BOOST_DEDUCED_TYPENAME base_type::size_type       size_type;               \
828     typedef BOOST_DEDUCED_TYPENAME base_type::const_reference const_reference;         \
829     typedef BOOST_DEDUCED_TYPENAME base_type::allocator_type  allocator_type;          \
830     PC() {}                                                                            \
831     explicit PC( const allocator_type& a ) : base_type(a) {}                           \
832     template< class InputIterator >                                                    \
833     PC( InputIterator first, InputIterator last ) : base_type( first, last ) {}        \
834     template< class InputIterator >                                                    \
835     PC( InputIterator first, InputIterator last,                                       \
836         const allocator_type& a ) : base_type( first, last, a ) {}
837 
838 #define BOOST_PTR_CONTAINER_DEFINE_NON_INHERITED_MEMBERS( PC, base_type, this_type )           \
839    BOOST_PTR_CONTAINER_DEFINE_CONSTRUCTORS( PC, base_type )                                    \
840    BOOST_PTR_CONTAINER_DEFINE_RELEASE_AND_CLONE( PC, base_type, this_type )
841 
842 #define BOOST_PTR_CONTAINER_DEFINE_SEQEUENCE_MEMBERS( PC, base_type, this_type )  \
843     BOOST_PTR_CONTAINER_DEFINE_NON_INHERITED_MEMBERS( PC, base_type, this_type )  \
844     BOOST_PTR_CONTAINER_DEFINE_COPY_CONSTRUCTORS( PC, base_type )
845 
846 } // namespace 'ptr_container_detail'
847 
848     //
849     // @remark: expose movability of internal move-pointer
850     //
851     namespace ptr_container
852     {
853         using ptr_container_detail::move;
854     }
855 
856 } // namespace 'boost'
857 
858 #if defined(BOOST_PTR_CONTAINER_DISABLE_DEPRECATED)
859 #pragma GCC diagnostic pop
860 #endif
861 
862 #if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
863 #pragma warning(pop)
864 #endif
865 
866 #endif
867