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_DETAIL_PTR_MAP_ADAPTER_HPP
13 #define BOOST_PTR_CONTAINER_DETAIL_PTR_MAP_ADAPTER_HPP
14 
15 #if defined(_MSC_VER) && (_MSC_VER >= 1200)
16 # pragma once
17 #endif
18 
19 #include <boost/ptr_container/detail/map_iterator.hpp>
20 #include <boost/ptr_container/detail/associative_ptr_container.hpp>
21 #include <boost/ptr_container/detail/meta_functions.hpp>
22 #include <boost/ptr_container/detail/ptr_container_disable_deprecated.hpp>
23 #include <boost/static_assert.hpp>
24 #include <boost/range/iterator_range.hpp>
25 
26 #if defined(BOOST_PTR_CONTAINER_DISABLE_DEPRECATED)
27 #pragma GCC diagnostic push
28 #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
29 #endif
30 
31 namespace boost
32 {
33 namespace ptr_container_detail
34 {
35 
36     template
37     <
38         class T,
39         class VoidPtrMap,
40         bool  Ordered
41     >
42     struct map_config
43     {
44         typedef BOOST_DEDUCED_TYPENAME remove_nullable<T>::type
45                      U;
46         typedef VoidPtrMap
47                      void_container_type;
48 
49         typedef BOOST_DEDUCED_TYPENAME VoidPtrMap::allocator_type
50                      allocator_type;
51 
52        typedef BOOST_DEDUCED_TYPENAME
53            mpl::eval_if_c<Ordered,
54                           select_value_compare<VoidPtrMap>,
55                           mpl::identity<void> >::type
56                     value_compare;
57 
58        typedef BOOST_DEDUCED_TYPENAME
59            mpl::eval_if_c<Ordered,
60                           select_key_compare<VoidPtrMap>,
61                           mpl::identity<void> >::type
62                     key_compare;
63 
64        typedef BOOST_DEDUCED_TYPENAME
65            mpl::eval_if_c<Ordered,
66                           mpl::identity<void>,
67                           select_hasher<VoidPtrMap> >::type
68                     hasher;
69 
70        typedef BOOST_DEDUCED_TYPENAME
71            mpl::eval_if_c<Ordered,
72                           mpl::identity<void>,
73                           select_key_equal<VoidPtrMap> >::type
74                     key_equal;
75 
76        typedef BOOST_DEDUCED_TYPENAME
77            mpl::if_c<Ordered,
78                      ptr_container_detail::ordered_associative_container_tag,
79                      ptr_container_detail::unordered_associative_container_tag>::type
80                     container_type;
81 
82         typedef BOOST_DEDUCED_TYPENAME VoidPtrMap::key_type
83                      key_type;
84 
85         typedef U    value_type;
86 
87         typedef ptr_map_iterator< BOOST_DEDUCED_TYPENAME VoidPtrMap::iterator, key_type, U* const >
88                      iterator;
89 
90         typedef ptr_map_iterator< BOOST_DEDUCED_TYPENAME VoidPtrMap::const_iterator, key_type, const U* const>
91                      const_iterator;
92 
93         typedef ptr_map_iterator<
94            BOOST_DEDUCED_TYPENAME
95              mpl::eval_if_c<Ordered,
96                             select_iterator<VoidPtrMap>,
97                             select_local_iterator<VoidPtrMap> >::type,
98              key_type, U* const >
99                     local_iterator;
100 
101        typedef ptr_map_iterator<
102            BOOST_DEDUCED_TYPENAME
103              mpl::eval_if_c<Ordered,
104                             select_iterator<VoidPtrMap>,
105                             select_const_local_iterator<VoidPtrMap> >::type,
106              key_type, const U* const >
107                     const_local_iterator;
108 
109         template< class Iter >
get_pointerboost::ptr_container_detail::map_config110         static U* get_pointer( Iter i )
111         {
112             return i->second;
113         }
114 
115         template< class Iter >
get_const_pointerboost::ptr_container_detail::map_config116         static const U* get_const_pointer( Iter i )
117         {
118             return i->second;
119         }
120 
121         BOOST_STATIC_CONSTANT( bool, allow_null = boost::is_nullable<T>::value );
122     };
123 
124 
125 
126     template
127     <
128         class T,
129         class VoidPtrMap,
130         class CloneAllocator,
131         bool  Ordered
132     >
133     class ptr_map_adapter_base :
134         public ptr_container_detail::associative_ptr_container< map_config<T,VoidPtrMap,Ordered>,
135                                                     CloneAllocator >
136     {
137         typedef ptr_container_detail::associative_ptr_container< map_config<T,VoidPtrMap,Ordered>,
138                                                      CloneAllocator >
139             base_type;
140 
141         typedef map_config<T,VoidPtrMap,Ordered>                           config;
142         typedef ptr_map_adapter_base<T,VoidPtrMap,CloneAllocator,Ordered>  this_type;
143 
144     public:
145 
146         typedef BOOST_DEDUCED_TYPENAME base_type::allocator_type
147                     allocator_type;
148         typedef BOOST_DEDUCED_TYPENAME base_type::iterator
149                     iterator;
150         typedef BOOST_DEDUCED_TYPENAME base_type::const_iterator
151                     const_iterator;
152         typedef BOOST_DEDUCED_TYPENAME base_type::size_type
153                     size_type;
154         typedef BOOST_DEDUCED_TYPENAME base_type::key_type
155                     key_type;
156         typedef BOOST_DEDUCED_TYPENAME base_type::auto_type
157                     auto_type;
158         typedef BOOST_DEDUCED_TYPENAME base_type::value_type
159                     mapped_type;
160         typedef BOOST_DEDUCED_TYPENAME base_type::reference
161                     mapped_reference;
162         typedef BOOST_DEDUCED_TYPENAME base_type::const_reference
163                     const_mapped_reference;
164         typedef BOOST_DEDUCED_TYPENAME iterator_value<iterator>::type
165                     value_type;
166         typedef value_type
167                     reference;
168         typedef BOOST_DEDUCED_TYPENAME iterator_value<const_iterator>::type
169                     const_reference;
170         typedef value_type
171                     pointer;
172         typedef const_reference
173                     const_pointer;
174 
175     private:
lookup(const key_type & key) const176         const_mapped_reference lookup( const key_type& key ) const
177         {
178            const_iterator i = this->find( key );
179            BOOST_PTR_CONTAINER_THROW_EXCEPTION( i == this->end(), bad_ptr_container_operation,
180                                                 "'ptr_map/multimap::at()' could"
181                                                 " not find key" );
182            return *i->second;
183         }
184 
185         struct eraser // scope guard
186         {
187             bool            released_;
188             VoidPtrMap*     m_;
189             const key_type& key_;
190 
eraserboost::ptr_container_detail::ptr_map_adapter_base::eraser191             eraser( VoidPtrMap* m, const key_type& key )
192               : released_(false), m_(m), key_(key)
193             {}
194 
~eraserboost::ptr_container_detail::ptr_map_adapter_base::eraser195             ~eraser()
196             {
197                 if( !released_ )
198                     m_->erase(key_);
199             }
200 
releaseboost::ptr_container_detail::ptr_map_adapter_base::eraser201             void release() { released_ = true; }
202 
203         private:
204             eraser& operator=(const eraser&);
205         };
206 
insert_lookup(const key_type & key)207         mapped_reference insert_lookup( const key_type& key )
208         {
209             void*& ref = this->base()[key];
210             if( ref )
211             {
212                 return *static_cast<mapped_type>(ref);
213             }
214             else
215             {
216                 eraser e(&this->base(),key);      // nothrow
217                 mapped_type res = new T();        // strong
218                 ref = res;                        // nothrow
219                 e.release();                      // nothrow
220                 return *res;
221             }
222           }
223 
224     public:
225 
ptr_map_adapter_base()226         ptr_map_adapter_base()
227         { }
228 
229         template< class SizeType >
ptr_map_adapter_base(SizeType n,ptr_container_detail::unordered_associative_container_tag tag)230         explicit ptr_map_adapter_base( SizeType n,
231                                        ptr_container_detail::unordered_associative_container_tag tag )
232         : base_type( n, tag )
233         { }
234 
235         template< class Compare, class Allocator >
ptr_map_adapter_base(const Compare & comp,const Allocator & a)236         ptr_map_adapter_base( const Compare& comp,
237                               const Allocator& a )
238         : base_type( comp, a )
239         { }
240 
241         template< class Hash, class Pred, class Allocator >
ptr_map_adapter_base(const Hash & hash,const Pred & pred,const Allocator & a)242         ptr_map_adapter_base( const Hash& hash,
243                               const Pred& pred,
244                               const Allocator& a )
245          : base_type( hash, pred, a )
246         { }
247 
248         template< class InputIterator >
ptr_map_adapter_base(InputIterator first,InputIterator last)249         ptr_map_adapter_base( InputIterator first, InputIterator last )
250          : base_type( first, last )
251         { }
252 
253         template< class InputIterator, class Comp >
ptr_map_adapter_base(InputIterator first,InputIterator last,const Comp & comp,const allocator_type & a=allocator_type ())254         ptr_map_adapter_base( InputIterator first, InputIterator last,
255                               const Comp& comp,
256                               const allocator_type& a = allocator_type() )
257         : base_type( first, last, comp, a )
258         { }
259 
260         template< class InputIterator, class Hash, class Pred, class Allocator >
ptr_map_adapter_base(InputIterator first,InputIterator last,const Hash & hash,const Pred & pred,const Allocator & a)261         ptr_map_adapter_base( InputIterator first, InputIterator last,
262                               const Hash& hash,
263                               const Pred& pred,
264                               const Allocator& a )
265          : base_type( first, last, hash, pred, a )
266         { }
267 
268 #ifndef BOOST_NO_AUTO_PTR
269         template< class PtrContainer >
ptr_map_adapter_base(std::auto_ptr<PtrContainer> clone)270         explicit ptr_map_adapter_base( std::auto_ptr<PtrContainer> clone )
271         : base_type( clone )
272         { }
273 
274         template< typename PtrContainer >
operator =(std::auto_ptr<PtrContainer> clone)275         ptr_map_adapter_base& operator=( std::auto_ptr<PtrContainer> clone )
276         {
277             base_type::operator=( clone );
278             return *this;
279         }
280 #endif
281 #ifndef BOOST_NO_CXX11_SMART_PTR
282         template< class PtrContainer >
ptr_map_adapter_base(std::unique_ptr<PtrContainer> clone)283         explicit ptr_map_adapter_base( std::unique_ptr<PtrContainer> clone )
284         : base_type( std::move( clone ) )
285         { }
286 
287         template< typename PtrContainer >
operator =(std::unique_ptr<PtrContainer> clone)288         ptr_map_adapter_base& operator=( std::unique_ptr<PtrContainer> clone )
289         {
290             base_type::operator=( std::move( clone ) );
291             return *this;
292         }
293 #endif
294 
find(const key_type & x)295         iterator find( const key_type& x )
296         {
297             return iterator( this->base().find( x ) );
298         }
299 
find(const key_type & x) const300         const_iterator find( const key_type& x ) const
301         {
302             return const_iterator( this->base().find( x ) );
303         }
304 
count(const key_type & x) const305         size_type count( const key_type& x ) const
306         {
307             return this->base().count( x );
308         }
309 
lower_bound(const key_type & x)310         iterator lower_bound( const key_type& x )
311         {
312             return iterator( this->base().lower_bound( x ) );
313         }
314 
lower_bound(const key_type & x) const315         const_iterator lower_bound( const key_type& x ) const
316         {
317             return const_iterator( this->base().lower_bound( x ) );
318         }
319 
upper_bound(const key_type & x)320         iterator upper_bound( const key_type& x )
321         {
322             return iterator( this->base().upper_bound( x ) );
323         }
324 
upper_bound(const key_type & x) const325         const_iterator upper_bound( const key_type& x ) const
326         {
327             return const_iterator( this->base().upper_bound( x ) );
328         }
329 
equal_range(const key_type & x)330         iterator_range<iterator> equal_range( const key_type& x )
331         {
332             std::pair<BOOST_DEDUCED_TYPENAME base_type::ptr_iterator,
333                       BOOST_DEDUCED_TYPENAME base_type::ptr_iterator>
334                  p = this->base().equal_range( x );
335             return make_iterator_range( iterator( p.first ), iterator( p.second ) );
336         }
337 
equal_range(const key_type & x) const338         iterator_range<const_iterator> equal_range( const key_type& x ) const
339         {
340             std::pair<BOOST_DEDUCED_TYPENAME base_type::ptr_const_iterator,
341                       BOOST_DEDUCED_TYPENAME base_type::ptr_const_iterator>
342                 p = this->base().equal_range( x );
343             return make_iterator_range( const_iterator( p.first ),
344                                         const_iterator( p.second ) );
345         }
346 
at(const key_type & key)347         mapped_reference at( const key_type& key )
348         {
349             return const_cast<mapped_reference>( lookup( key ) );
350         }
351 
at(const key_type & key) const352         const_mapped_reference at( const key_type& key ) const
353         {
354             return lookup( key );
355         }
356 
operator [](const key_type & key)357         mapped_reference operator[]( const key_type& key )
358         {
359             return insert_lookup( key );
360         }
361 
replace(iterator where,mapped_type x)362         auto_type replace( iterator where, mapped_type x ) // strong
363         {
364             BOOST_ASSERT( where != this->end() );
365             this->enforce_null_policy( x, "Null pointer in 'replace()'" );
366 
367             auto_type ptr( x, *this );
368             BOOST_PTR_CONTAINER_THROW_EXCEPTION( this->empty(),
369                                                  bad_ptr_container_operation,
370                                                  "'replace()' on empty container" );
371 
372             auto_type old( where->second, *this ); // nothrow
373             where.base()->second = ptr.release();  // nothrow, commit
374             return boost::ptr_container::move( old );
375         }
376 
377 #ifndef BOOST_NO_AUTO_PTR
378         template< class U >
replace(iterator where,std::auto_ptr<U> x)379         auto_type replace( iterator where, std::auto_ptr<U> x )
380         {
381             return replace( where, x.release() );
382         }
383 #endif
384 #ifndef BOOST_NO_CXX11_SMART_PTR
385         template< class U >
replace(iterator where,std::unique_ptr<U> x)386         auto_type replace( iterator where, std::unique_ptr<U> x )
387         {
388             return replace( where, x.release() );
389         }
390 #endif
391 
392     protected:
bucket(const key_type & key) const393         size_type bucket( const key_type& key ) const
394         {
395             return this->base().bucket( key );
396         }
397     };
398 
399 } // ptr_container_detail
400 
401     /////////////////////////////////////////////////////////////////////////
402     // ptr_map_adapter
403     /////////////////////////////////////////////////////////////////////////
404 
405     template
406     <
407         class T,
408         class VoidPtrMap,
409         class CloneAllocator = heap_clone_allocator,
410         bool  Ordered        = true
411     >
412     class ptr_map_adapter :
413         public ptr_container_detail::ptr_map_adapter_base<T,VoidPtrMap,CloneAllocator,Ordered>
414     {
415         typedef ptr_container_detail::ptr_map_adapter_base<T,VoidPtrMap,CloneAllocator,Ordered>
416             base_type;
417 
418     public:
419         typedef BOOST_DEDUCED_TYPENAME base_type::iterator
420                      iterator;
421         typedef BOOST_DEDUCED_TYPENAME base_type::const_iterator
422                      const_iterator;
423         typedef BOOST_DEDUCED_TYPENAME base_type::size_type
424                     size_type;
425         typedef BOOST_DEDUCED_TYPENAME base_type::key_type
426                     key_type;
427         typedef BOOST_DEDUCED_TYPENAME base_type::const_reference
428                     const_reference;
429         typedef BOOST_DEDUCED_TYPENAME base_type::auto_type
430                     auto_type;
431         typedef BOOST_DEDUCED_TYPENAME VoidPtrMap::allocator_type
432                     allocator_type;
433         typedef BOOST_DEDUCED_TYPENAME base_type::mapped_type
434                     mapped_type;
435     private:
436 
safe_insert(const key_type & key,auto_type ptr)437         void safe_insert( const key_type& key, auto_type ptr ) // strong
438         {
439             std::pair<BOOST_DEDUCED_TYPENAME base_type::ptr_iterator,bool>
440                 res =
441                 this->base().insert( std::make_pair( key, ptr.get() ) ); // strong, commit
442             if( res.second )                                             // nothrow
443                 ptr.release();                                           // nothrow
444         }
445 
446         template< class II >
map_basic_clone_and_insert(II first,II last)447         void map_basic_clone_and_insert( II first, II last )
448         {
449             while( first != last )
450             {
451                 if( this->find( first->first ) == this->end() )
452                 {
453                     const_reference p = *first.base();     // nothrow
454                     auto_type ptr( this->null_policy_allocate_clone(p.second), *this );
455                                                            // strong
456                     this->safe_insert( p.first,
457                                        boost::ptr_container::move( ptr ) );
458                                                            // strong, commit
459                 }
460                 ++first;
461             }
462         }
463 
464     public:
ptr_map_adapter()465         ptr_map_adapter( )
466         { }
467 
468         template< class Comp >
ptr_map_adapter(const Comp & comp,const allocator_type & a)469         explicit ptr_map_adapter( const Comp& comp,
470                                   const allocator_type& a )
471           : base_type( comp, a ) { }
472 
473         template< class SizeType >
ptr_map_adapter(SizeType n,ptr_container_detail::unordered_associative_container_tag tag)474         explicit ptr_map_adapter( SizeType n,
475             ptr_container_detail::unordered_associative_container_tag tag )
476           : base_type( n, tag ) { }
477 
478         template< class Hash, class Pred, class Allocator >
ptr_map_adapter(const Hash & hash,const Pred & pred,const Allocator & a)479         ptr_map_adapter( const Hash& hash,
480                          const Pred& pred,
481                          const Allocator& a )
482          : base_type( hash, pred, a )
483         { }
484 
485         template< class InputIterator >
ptr_map_adapter(InputIterator first,InputIterator last)486         ptr_map_adapter( InputIterator first, InputIterator last )
487         {
488             map_basic_clone_and_insert( first, last );
489         }
490 
491         template< class InputIterator, class Comp >
ptr_map_adapter(InputIterator first,InputIterator last,const Comp & comp,const allocator_type & a=allocator_type ())492         ptr_map_adapter( InputIterator first, InputIterator last,
493                          const Comp& comp,
494                          const allocator_type& a = allocator_type() )
495           : base_type( comp, a )
496         {
497             map_basic_clone_and_insert( first, last );
498         }
499 
500         template< class InputIterator, class Hash, class Pred, class Allocator >
ptr_map_adapter(InputIterator first,InputIterator last,const Hash & hash,const Pred & pred,const Allocator & a)501         ptr_map_adapter( InputIterator first, InputIterator last,
502                          const Hash& hash,
503                          const Pred& pred,
504                          const Allocator& a )
505           : base_type( hash, pred, a )
506         {
507             map_basic_clone_and_insert( first, last );
508         }
509 
ptr_map_adapter(const ptr_map_adapter & r)510         ptr_map_adapter( const ptr_map_adapter& r )
511         {
512             map_basic_clone_and_insert( r.begin(), r.end() );
513         }
514 
515         template< class Key, class U, class CA, bool b >
ptr_map_adapter(const ptr_map_adapter<Key,U,CA,b> & r)516         ptr_map_adapter( const ptr_map_adapter<Key,U,CA,b>& r )
517         {
518             map_basic_clone_and_insert( r.begin(), r.end() );
519         }
520 
521 #ifndef BOOST_NO_AUTO_PTR
522         template< class U >
ptr_map_adapter(std::auto_ptr<U> r)523         ptr_map_adapter( std::auto_ptr<U> r ) : base_type( r )
524         { }
525 #endif
526 #ifndef BOOST_NO_CXX11_SMART_PTR
527         template< class U >
ptr_map_adapter(std::unique_ptr<U> r)528         ptr_map_adapter( std::unique_ptr<U> r ) : base_type( std::move( r ) )
529         { }
530 #endif
531 
operator =(ptr_map_adapter r)532         ptr_map_adapter& operator=( ptr_map_adapter r )
533         {
534             this->swap( r );
535             return *this;
536         }
537 
538 #ifndef BOOST_NO_AUTO_PTR
539         template< class U >
operator =(std::auto_ptr<U> r)540         ptr_map_adapter& operator=( std::auto_ptr<U> r )
541         {
542             base_type::operator=( r );
543             return *this;
544         }
545 #endif
546 #ifndef BOOST_NO_CXX11_SMART_PTR
547         template< class U >
operator =(std::unique_ptr<U> r)548         ptr_map_adapter& operator=( std::unique_ptr<U> r )
549         {
550             base_type::operator=( std::move( r ) );
551             return *this;
552         }
553 #endif
554 
555         using base_type::release;
556 
557         template< typename InputIterator >
insert(InputIterator first,InputIterator last)558         void insert( InputIterator first, InputIterator last ) // basic
559         {
560             map_basic_clone_and_insert( first, last );
561         }
562 
563         template< class Range >
insert(const Range & r)564         void insert( const Range& r )
565         {
566             insert( boost::begin(r), boost::end(r) );
567         }
568 
569     private:
insert_impl(const key_type & key,mapped_type x)570         std::pair<iterator,bool> insert_impl( const key_type& key, mapped_type x ) // strong
571         {
572             this->enforce_null_policy( x, "Null pointer in ptr_map_adapter::insert()" );
573 
574             auto_type ptr( x, *this );                                  // nothrow
575             std::pair<BOOST_DEDUCED_TYPENAME base_type::ptr_iterator,bool>
576                  res = this->base().insert( std::make_pair( key, x ) ); // strong, commit
577             if( res.second )                                            // nothrow
578                 ptr.release();                                          // nothrow
579             return std::make_pair( iterator( res.first ), res.second ); // nothrow
580         }
581 
insert_impl(iterator before,const key_type & key,mapped_type x)582         iterator insert_impl( iterator before, const key_type& key, mapped_type x ) // strong
583         {
584             this->enforce_null_policy( x,
585                   "Null pointer in 'ptr_map_adapter::insert()'" );
586 
587             auto_type ptr( x, *this );  // nothrow
588             BOOST_DEDUCED_TYPENAME base_type::ptr_iterator
589                 res = this->base().insert( before.base(), std::make_pair( key, x ) );
590                                         // strong, commit
591             ptr.release();              // notrow
592             return iterator( res );
593         }
594 
595     public:
596 
insert(key_type & key,mapped_type x)597         std::pair<iterator,bool> insert( key_type& key, mapped_type x )
598         {
599             return insert_impl( key, x );
600         }
601 
602 #ifndef BOOST_NO_AUTO_PTR
603         template< class U >
insert(const key_type & key,std::auto_ptr<U> x)604         std::pair<iterator,bool> insert( const key_type& key, std::auto_ptr<U> x )
605         {
606             return insert_impl( key, x.release() );
607         }
608 #endif
609 #ifndef BOOST_NO_CXX11_SMART_PTR
610         template< class U >
insert(const key_type & key,std::unique_ptr<U> x)611         std::pair<iterator,bool> insert( const key_type& key, std::unique_ptr<U> x )
612         {
613             return insert_impl( key, x.release() );
614         }
615 #endif
616 
617         template< class F, class S >
insert(iterator before,ptr_container_detail::ref_pair<F,S> p)618         iterator insert( iterator before, ptr_container_detail::ref_pair<F,S> p ) // strong
619         {
620             this->enforce_null_policy( p.second,
621                   "Null pointer in 'ptr_map_adapter::insert()'" );
622 
623             auto_type ptr( this->null_policy_allocate_clone(p.second), *this );
624             BOOST_DEDUCED_TYPENAME base_type::ptr_iterator
625                 result = this->base().insert( before.base(),
626                                      std::make_pair(p.first,ptr.get()) ); // strong
627             if( ptr.get() == result->second )
628                 ptr.release();
629 
630             return iterator( result );
631         }
632 
insert(iterator before,key_type & key,mapped_type x)633         iterator insert( iterator before, key_type& key, mapped_type x ) // strong
634         {
635             return insert_impl( before, key, x );
636         }
637 
638 #ifndef BOOST_NO_AUTO_PTR
639         template< class U >
insert(iterator before,const key_type & key,std::auto_ptr<U> x)640         iterator insert( iterator before, const key_type& key, std::auto_ptr<U> x ) // strong
641         {
642             return insert_impl( before, key, x.release() );
643         }
644 #endif
645 #ifndef BOOST_NO_CXX11_SMART_PTR
646         template< class U >
insert(iterator before,const key_type & key,std::unique_ptr<U> x)647         iterator insert( iterator before, const key_type& key, std::unique_ptr<U> x ) // strong
648         {
649             return insert_impl( before, key, x.release() );
650         }
651 #endif
652 
653         template< class PtrMapAdapter >
transfer(BOOST_DEDUCED_TYPENAME PtrMapAdapter::iterator object,PtrMapAdapter & from)654         bool transfer( BOOST_DEDUCED_TYPENAME PtrMapAdapter::iterator object,
655                        PtrMapAdapter& from ) // strong
656         {
657             return this->single_transfer( object, from );
658         }
659 
660         template< class PtrMapAdapter >
transfer(BOOST_DEDUCED_TYPENAME PtrMapAdapter::iterator first,BOOST_DEDUCED_TYPENAME PtrMapAdapter::iterator last,PtrMapAdapter & from)661         size_type transfer( BOOST_DEDUCED_TYPENAME PtrMapAdapter::iterator first,
662                             BOOST_DEDUCED_TYPENAME PtrMapAdapter::iterator last,
663                             PtrMapAdapter& from ) // basic
664         {
665             return this->single_transfer( first, last, from );
666         }
667 
668 #if defined(BOOST_NO_SFINAE) || defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING)
669 #else
670 
671         template< class PtrMapAdapter, class Range >
672         BOOST_DEDUCED_TYPENAME boost::disable_if< boost::is_same< Range,
673                             BOOST_DEDUCED_TYPENAME PtrMapAdapter::iterator >,
674                                                             size_type >::type
transfer(const Range & r,PtrMapAdapter & from)675         transfer( const Range& r, PtrMapAdapter& from ) // basic
676         {
677             return transfer( boost::begin(r), boost::end(r), from );
678         }
679 
680 #endif
681 
682         template< class PtrMapAdapter >
transfer(PtrMapAdapter & from)683         size_type transfer( PtrMapAdapter& from ) // basic
684         {
685             return transfer( from.begin(), from.end(), from );
686         }
687   };
688 
689   /////////////////////////////////////////////////////////////////////////
690   // ptr_multimap_adapter
691   /////////////////////////////////////////////////////////////////////////
692 
693     template
694     <
695         class T,
696         class VoidPtrMultiMap,
697         class CloneAllocator = heap_clone_allocator,
698         bool  Ordered        = true
699     >
700     class ptr_multimap_adapter :
701         public ptr_container_detail::ptr_map_adapter_base<T,VoidPtrMultiMap,CloneAllocator,Ordered>
702     {
703         typedef ptr_container_detail::ptr_map_adapter_base<T,VoidPtrMultiMap,CloneAllocator,Ordered>
704              base_type;
705 
706     public: // typedefs
707         typedef BOOST_DEDUCED_TYPENAME base_type::iterator
708                        iterator;
709         typedef BOOST_DEDUCED_TYPENAME base_type::const_iterator
710                        const_iterator;
711         typedef BOOST_DEDUCED_TYPENAME base_type::size_type
712                        size_type;
713         typedef BOOST_DEDUCED_TYPENAME base_type::key_type
714                        key_type;
715         typedef BOOST_DEDUCED_TYPENAME base_type::const_reference
716                        const_reference;
717         typedef BOOST_DEDUCED_TYPENAME base_type::mapped_type
718                     mapped_type;
719         typedef BOOST_DEDUCED_TYPENAME base_type::auto_type
720                     auto_type;
721         typedef BOOST_DEDUCED_TYPENAME VoidPtrMultiMap::allocator_type
722                     allocator_type;
723     private:
724 
safe_insert(const key_type & key,auto_type ptr)725         void safe_insert( const key_type& key, auto_type ptr ) // strong
726         {
727             this->base().insert(
728                            std::make_pair( key, ptr.get() ) ); // strong, commit
729             ptr.release();                                     // nothrow
730         }
731 
732         template< typename II >
map_basic_clone_and_insert(II first,II last)733         void map_basic_clone_and_insert( II first, II last )
734         {
735             while( first != last )
736             {
737                 const_reference pair = *first.base();     // nothrow
738                 auto_type ptr( this->null_policy_allocate_clone(pair.second), *this );
739                                                           // strong
740                 safe_insert( pair.first,
741                              boost::ptr_container::move( ptr ) );
742                                                           // strong, commit
743                 ++first;
744             }
745         }
746 
747     public:
748 
ptr_multimap_adapter()749         ptr_multimap_adapter()
750         { }
751 
752         template< class SizeType >
ptr_multimap_adapter(SizeType n,ptr_container_detail::unordered_associative_container_tag tag)753         ptr_multimap_adapter( SizeType n,
754                               ptr_container_detail::unordered_associative_container_tag tag )
755           : base_type( n, tag )
756         { }
757 
758         template< class Comp >
ptr_multimap_adapter(const Comp & comp,const allocator_type & a)759         explicit ptr_multimap_adapter( const Comp& comp,
760                                        const allocator_type& a )
761           : base_type( comp, a ) { }
762 
763         template< class Hash, class Pred, class Allocator >
ptr_multimap_adapter(const Hash & hash,const Pred & pred,const Allocator & a)764         ptr_multimap_adapter( const Hash& hash,
765                               const Pred& pred,
766                               const Allocator& a )
767          : base_type( hash, pred, a )
768         { }
769 
770         template< class InputIterator >
ptr_multimap_adapter(InputIterator first,InputIterator last)771         ptr_multimap_adapter( InputIterator first, InputIterator last )
772         {
773             map_basic_clone_and_insert( first, last );
774         }
775 
776         template< class InputIterator, class Comp >
ptr_multimap_adapter(InputIterator first,InputIterator last,const Comp & comp,const allocator_type & a)777         ptr_multimap_adapter( InputIterator first, InputIterator last,
778                               const Comp& comp,
779                               const allocator_type& a )
780           : base_type( comp, a )
781         {
782             map_basic_clone_and_insert( first, last );
783         }
784 
785         template< class InputIterator, class Hash, class Pred, class Allocator >
ptr_multimap_adapter(InputIterator first,InputIterator last,const Hash & hash,const Pred & pred,const Allocator & a)786         ptr_multimap_adapter( InputIterator first, InputIterator last,
787                               const Hash& hash,
788                               const Pred& pred,
789                               const Allocator& a )
790          : base_type( hash, pred, a )
791         {
792             map_basic_clone_and_insert( first, last );
793         }
794 
ptr_multimap_adapter(const ptr_multimap_adapter & r)795         ptr_multimap_adapter( const ptr_multimap_adapter& r )
796         {
797             map_basic_clone_and_insert( r.begin(), r.end() );
798         }
799 
800         template< class Key, class U, class CA, bool b >
ptr_multimap_adapter(const ptr_multimap_adapter<Key,U,CA,b> & r)801         ptr_multimap_adapter( const ptr_multimap_adapter<Key,U,CA,b>& r )
802         {
803             map_basic_clone_and_insert( r.begin(), r.end() );
804         }
805 
806 #ifndef BOOST_NO_AUTO_PTR
807         template< class U >
ptr_multimap_adapter(std::auto_ptr<U> r)808         explicit ptr_multimap_adapter( std::auto_ptr<U> r ) : base_type( r )
809         { }
810 #endif
811 #ifndef BOOST_NO_CXX11_SMART_PTR
812         template< class U >
ptr_multimap_adapter(std::unique_ptr<U> r)813         explicit ptr_multimap_adapter( std::unique_ptr<U> r ) : base_type( std::move( r ) )
814         { }
815 #endif
816 
operator =(ptr_multimap_adapter r)817         ptr_multimap_adapter& operator=( ptr_multimap_adapter r )
818         {
819             this->swap( r );
820             return *this;
821         }
822 
823 #ifndef BOOST_NO_AUTO_PTR
824         template< class U >
operator =(std::auto_ptr<U> r)825         ptr_multimap_adapter& operator=( std::auto_ptr<U> r )
826         {
827             base_type::operator=( r );
828             return *this;
829         }
830 #endif
831 #ifndef BOOST_NO_CXX11_SMART_PTR
832         template< class U >
operator =(std::unique_ptr<U> r)833         ptr_multimap_adapter& operator=( std::unique_ptr<U> r )
834         {
835             base_type::operator=( std::move( r ) );
836             return *this;
837         }
838 #endif
839 
840         using base_type::release;
841 
842     private:
insert_impl(const key_type & key,mapped_type x)843         iterator insert_impl( const key_type& key, mapped_type x ) // strong
844         {
845             this->enforce_null_policy( x,
846                   "Null pointer in 'ptr_multimap_adapter::insert()'" );
847 
848             auto_type ptr( x, *this );  // nothrow
849             BOOST_DEDUCED_TYPENAME base_type::ptr_iterator
850                 res = this->base().insert( std::make_pair( key, x ) );
851                                         // strong, commit
852             ptr.release();              // notrow
853             return iterator( res );
854         }
855 
insert_impl(iterator before,const key_type & key,mapped_type x)856         iterator insert_impl( iterator before, const key_type& key, mapped_type x ) // strong
857         {
858             this->enforce_null_policy( x,
859                   "Null pointer in 'ptr_multimap_adapter::insert()'" );
860 
861             auto_type ptr( x, *this );  // nothrow
862             BOOST_DEDUCED_TYPENAME base_type::ptr_iterator
863                 res = this->base().insert( before.base(),
864                                            std::make_pair( key, x ) );
865                                         // strong, commit
866             ptr.release();              // notrow
867             return iterator( res );
868         }
869 
870     public:
871         template< typename InputIterator >
insert(InputIterator first,InputIterator last)872         void insert( InputIterator first, InputIterator last ) // basic
873         {
874             map_basic_clone_and_insert( first, last );
875         }
876 
877         template< class Range >
insert(const Range & r)878         void insert( const Range& r )
879         {
880             insert( boost::begin(r), boost::end(r) );
881         }
882 
insert(key_type & key,mapped_type x)883         iterator insert( key_type& key, mapped_type x ) // strong
884         {
885             return insert_impl( key, x );
886         }
887 
888 #ifndef BOOST_NO_AUTO_PTR
889         template< class U >
insert(const key_type & key,std::auto_ptr<U> x)890         iterator insert( const key_type& key, std::auto_ptr<U> x )
891         {
892             return insert_impl( key, x.release() );
893         }
894 #endif
895 #ifndef BOOST_NO_CXX11_SMART_PTR
896         template< class U >
insert(const key_type & key,std::unique_ptr<U> x)897         iterator insert( const key_type& key, std::unique_ptr<U> x )
898         {
899             return insert_impl( key, x.release() );
900         }
901 #endif
902 
903         template< class F, class S >
insert(iterator before,ptr_container_detail::ref_pair<F,S> p)904         iterator insert( iterator before, ptr_container_detail::ref_pair<F,S> p ) // strong
905         {
906             this->enforce_null_policy( p.second,
907                   "Null pointer in 'ptr_multimap_adapter::insert()'" );
908             iterator res = insert_impl( before, p.first,
909                                         this->null_policy_allocate_clone( p.second ) );
910             return res;
911         }
912 
insert(iterator before,key_type & key,mapped_type x)913         iterator insert( iterator before, key_type& key, mapped_type x ) // strong
914         {
915             return insert_impl( before, key, x );
916         }
917 
918 #ifndef BOOST_NO_AUTO_PTR
919         template< class U >
insert(iterator before,const key_type & key,std::auto_ptr<U> x)920         iterator insert( iterator before, const key_type& key, std::auto_ptr<U> x ) // strong
921         {
922             return insert_impl( before, key, x.release() );
923         }
924 #endif
925 #ifndef BOOST_NO_CXX11_SMART_PTR
926         template< class U >
insert(iterator before,const key_type & key,std::unique_ptr<U> x)927         iterator insert( iterator before, const key_type& key, std::unique_ptr<U> x ) // strong
928         {
929             return insert_impl( before, key, x.release() );
930         }
931 #endif
932 
933         template< class PtrMapAdapter >
transfer(BOOST_DEDUCED_TYPENAME PtrMapAdapter::iterator object,PtrMapAdapter & from)934         void transfer( BOOST_DEDUCED_TYPENAME PtrMapAdapter::iterator object,
935                        PtrMapAdapter& from ) // strong
936         {
937             this->multi_transfer( object, from );
938         }
939 
940         template< class PtrMapAdapter >
transfer(BOOST_DEDUCED_TYPENAME PtrMapAdapter::iterator first,BOOST_DEDUCED_TYPENAME PtrMapAdapter::iterator last,PtrMapAdapter & from)941         size_type transfer( BOOST_DEDUCED_TYPENAME PtrMapAdapter::iterator first,
942                             BOOST_DEDUCED_TYPENAME PtrMapAdapter::iterator last,
943                             PtrMapAdapter& from ) // basic
944         {
945             return this->multi_transfer( first, last, from );
946         }
947 
948 #if defined(BOOST_NO_SFINAE) || defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING)
949 #else
950 
951         template<  class PtrMapAdapter, class Range >
952         BOOST_DEDUCED_TYPENAME boost::disable_if< boost::is_same< Range,
953                             BOOST_DEDUCED_TYPENAME PtrMapAdapter::iterator >,
954                                                             size_type >::type
transfer(const Range & r,PtrMapAdapter & from)955         transfer( const Range& r, PtrMapAdapter& from ) // basic
956         {
957             return transfer( boost::begin(r), boost::end(r), from );
958         }
959 
960 #endif
961         template< class PtrMapAdapter >
transfer(PtrMapAdapter & from)962         void transfer( PtrMapAdapter& from ) // basic
963         {
964             transfer( from.begin(), from.end(), from );
965             BOOST_ASSERT( from.empty() );
966         }
967 
968     };
969 
970     template< class I, class F, class S >
is_null(const ptr_map_iterator<I,F,S> & i)971     inline bool is_null( const ptr_map_iterator<I,F,S>& i )
972     {
973         return i->second == 0;
974     }
975 
976 } // namespace 'boost'
977 
978 #if defined(BOOST_PTR_CONTAINER_DISABLE_DEPRECATED)
979 #pragma GCC diagnostic pop
980 #endif
981 
982 #endif
983