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/core/invoke_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
54namespace boost
55{
56
57namespace ptr_container_detail
58{
59 template< class Container >
60 struct dynamic_clone_deleter
61 {
62 dynamic_clone_deleter() { }
63 dynamic_clone_deleter( Container& cont ) : cont(&cont) { }
64 Container* cont;
65
66 template< class T >
67 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 {
77 static_clone_deleter() { }
78 template< class Dummy >
79 static_clone_deleter( const Dummy& ) { }
80
81 template< class T >
82 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:
124 container_type& base() { return c_; }
125 protected: // having this public could break encapsulation
126 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 >
168 void copy( InputIterator first, InputIterator last )
169 {
170 std::copy( first, last, begin() );
171 }
172
173 void copy( const reversible_ptr_container& r )
174 {
175 this->copy( r.begin(), r.end() );
176 }
177
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 >
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 >
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
203 void remove_all()
204 {
205 this->remove( begin(), end() );
206 }
207
208 protected:
209
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
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 >
229 void remove( U* ptr )
230 {
231 this->deallocate_clone( ptr );
232 }
233
234 template< class I >
235 void remove( I i )
236 {
237 this->deallocate_clone( Config::get_const_pointer(i) );
238 }
239
240 template< class I >
241 void remove( I first, I last )
242 {
243 for( ; first != last; ++first )
244 this->remove( first );
245 }
246
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:
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 >
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
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 >
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 >
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 >
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 >
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.
332 reversible_ptr_container()
333 { }
334
335 template< class SizeType >
336 reversible_ptr_container( SizeType n, unordered_associative_container_tag )
337 : c_( n )
338 { }
339
340 template< class SizeType >
341 reversible_ptr_container( SizeType n, fixed_length_sequence_tag )
342 : c_( n )
343 { }
344
345 template< class SizeType >
346 reversible_ptr_container( SizeType n, const allocator_type& a,
347 fixed_length_sequence_tag )
348 : c_( n, a )
349 { }
350
351 explicit reversible_ptr_container( const allocator_type& a )
352 : c_( a )
353 { }
354
355#ifndef BOOST_NO_AUTO_PTR
356 template< class PtrContainer >
357 explicit reversible_ptr_container( std::auto_ptr<PtrContainer> clone )
358 {
359 swap( r&: *clone );
360 }
361#endif
362#ifndef BOOST_NO_CXX11_SMART_PTR
363 template< class PtrContainer >
364 explicit reversible_ptr_container( std::unique_ptr<PtrContainer> clone )
365 {
366 swap( r&: *clone );
367 }
368#endif
369
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 >
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 >
383 reversible_ptr_container& operator=( std::auto_ptr<PtrContainer> clone ) // nothrow
384 {
385 swap( r&: *clone );
386 return *this;
387 }
388#endif
389#ifndef BOOST_NO_CXX11_SMART_PTR
390 template< class PtrContainer >
391 reversible_ptr_container& operator=( std::unique_ptr<PtrContainer> clone ) // nothrow
392 {
393 swap( r&: *clone );
394 return *this;
395 }
396#endif
397
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 >
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(BOOST_BORLANDC, BOOST_TESTED_AT(0x564))
414#else
415 BOOST_DEDUCED_TYPENAME
416#endif
417 iterator_category<InputIterator>::type() );
418 }
419
420 template< class Compare >
421 reversible_ptr_container( const Compare& comp,
422 const allocator_type& a )
423 : c_( comp, a ) {}
424
425 template< class ForwardIterator >
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 >
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(BOOST_BORLANDC, BOOST_TESTED_AT(0x564))
444#else
445 BOOST_DEDUCED_TYPENAME
446#endif
447 iterator_category<InputIterator>::type() );
448 }
449
450 template< class Compare >
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 >
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 >
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
476 explicit reversible_ptr_container( size_type n )
477 : c_( n ) {}
478
479 template< class Hash, class Pred >
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 >
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:
497 ~reversible_ptr_container()
498 {
499 remove_all();
500 }
501
502 public:
503
504 allocator_type get_allocator() const
505 {
506 return c_.get_allocator();
507 }
508
509 clone_allocator_type& get_clone_allocator()
510 {
511 return static_cast<clone_allocator_type&>(*this);
512 }
513
514 const clone_allocator_type& get_clone_allocator() const
515 {
516 return static_cast<const clone_allocator_type&>(*this);
517 }
518
519 public: // container requirements
520 iterator begin()
521 { return iterator( c_.begin() ); }
522 const_iterator begin() const
523 { return const_iterator( c_.begin() ); }
524 iterator end()
525 { return iterator( c_.end() ); }
526 const_iterator end() const
527 { return const_iterator( c_.end() ); }
528
529 reverse_iterator rbegin()
530 { return reverse_iterator( this->end() ); }
531 const_reverse_iterator rbegin() const
532 { return const_reverse_iterator( this->end() ); }
533 reverse_iterator rend()
534 { return reverse_iterator( this->begin() ); }
535 const_reverse_iterator rend() const
536 { return const_reverse_iterator( this->begin() ); }
537
538 const_iterator cbegin() const
539 { return const_iterator( c_.begin() ); }
540 const_iterator cend() const
541 { return const_iterator( c_.end() ); }
542
543 const_reverse_iterator crbegin() const
544 { return const_reverse_iterator( this->end() ); }
545 const_reverse_iterator crend() const
546 { return const_reverse_iterator( this->begin() ); }
547
548 void swap( reversible_ptr_container& r ) // nothrow
549 {
550 boost::core::invoke_swap( get_clone_allocator(), r.get_clone_allocator() ); // nothrow
551 c_.swap( r.c_ ); // nothrow
552 }
553
554 size_type size() const // nothrow
555 {
556 return c_.size();
557 }
558
559 size_type max_size() const // nothrow
560 {
561 return c_.max_size();
562 }
563
564 bool empty() const // nothrow
565 {
566 return c_.empty();
567 }
568
569 public: // optional container requirements
570
571 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
579 bool operator!=( const reversible_ptr_container& r ) const // nothrow
580 {
581 return !(*this == r);
582 }
583
584 bool operator<( const reversible_ptr_container& r ) const // nothrow
585 {
586 return std::lexicographical_compare( begin(), end(), r.begin(), r.end() );
587 }
588
589 bool operator<=( const reversible_ptr_container& r ) const // nothrow
590 {
591 return !(r < *this);
592 }
593
594 bool operator>( const reversible_ptr_container& r ) const // nothrow
595 {
596 return r < *this;
597 }
598
599 bool operator>=( const reversible_ptr_container& r ) const // nothrow
600 {
601 return !(*this < r);
602 }
603
604 public: // modifiers
605
606 iterator insert( iterator before, Ty_* x )
607 {
608 enforce_null_policy( x, msg: "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 >
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 >
625 iterator insert( iterator before, std::unique_ptr<U> x )
626 {
627 return insert( before, x.release() );
628 }
629#endif
630
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
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 >
648 iterator erase( const Range& r )
649 {
650 return erase( boost::begin(r), boost::end(r) );
651 }
652
653 void clear()
654 {
655 remove_all();
656 c_.clear();
657 }
658
659 public: // access interface
660
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
673 auto_type replace( iterator where, Ty_* x ) // strong
674 {
675 BOOST_ASSERT( where != end() );
676 enforce_null_policy( x, msg: "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 >
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 >
696 auto_type replace( iterator where, std::unique_ptr<U> x )
697 {
698 return replace( where, x.release() );
699 }
700#endif
701
702 auto_type replace( size_type idx, Ty_* x ) // strong
703 {
704 enforce_null_policy( x, msg: "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 >
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 >
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(BOOST_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

source code of boost/libs/ptr_container/include/boost/ptr_container/detail/reversible_ptr_container.hpp