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