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 > |
104 | static U* get_pointer( Iter i ) |
105 | { |
106 | return i->second; |
107 | } |
108 | |
109 | template< class Iter > |
110 | 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: |
170 | 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 | |
187 | eraser( VoidPtrMap* m, const key_type& key ) |
188 | : released_(false), m_(m), key_(key) |
189 | {} |
190 | |
191 | ~eraser() |
192 | { |
193 | if( !released_ ) |
194 | m_->erase(key_); |
195 | } |
196 | |
197 | void release() { released_ = true; } |
198 | |
199 | private: |
200 | eraser& operator=(const eraser&); |
201 | }; |
202 | |
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 | |
222 | ptr_map_adapter_base() |
223 | { } |
224 | |
225 | template< class SizeType > |
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 > |
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 > |
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 > |
245 | ptr_map_adapter_base( InputIterator first, InputIterator last ) |
246 | : base_type( first, last ) |
247 | { } |
248 | |
249 | template< class InputIterator, class Comp > |
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 > |
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 > |
265 | explicit ptr_map_adapter_base( std::auto_ptr<PtrContainer> clone ) |
266 | : base_type( clone ) |
267 | { } |
268 | |
269 | template< typename PtrContainer > |
270 | ptr_map_adapter_base& operator=( std::auto_ptr<PtrContainer> clone ) |
271 | { |
272 | base_type::operator=( clone ); |
273 | return *this; |
274 | } |
275 | |
276 | iterator find( const key_type& x ) |
277 | { |
278 | return iterator( this->base().find( x ) ); |
279 | } |
280 | |
281 | const_iterator find( const key_type& x ) const |
282 | { |
283 | return const_iterator( this->base().find( x ) ); |
284 | } |
285 | |
286 | size_type count( const key_type& x ) const |
287 | { |
288 | return this->base().count( x ); |
289 | } |
290 | |
291 | iterator lower_bound( const key_type& x ) |
292 | { |
293 | return iterator( this->base().lower_bound( x ) ); |
294 | } |
295 | |
296 | const_iterator lower_bound( const key_type& x ) const |
297 | { |
298 | return const_iterator( this->base().lower_bound( x ) ); |
299 | } |
300 | |
301 | iterator upper_bound( const key_type& x ) |
302 | { |
303 | return iterator( this->base().upper_bound( x ) ); |
304 | } |
305 | |
306 | const_iterator upper_bound( const key_type& x ) const |
307 | { |
308 | return const_iterator( this->base().upper_bound( x ) ); |
309 | } |
310 | |
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 | |
319 | 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 | |
328 | mapped_reference at( const key_type& key ) |
329 | { |
330 | return const_cast<mapped_reference>( lookup( key ) ); |
331 | } |
332 | |
333 | const_mapped_reference at( const key_type& key ) const |
334 | { |
335 | return lookup( key ); |
336 | } |
337 | |
338 | mapped_reference operator[]( const key_type& key ) |
339 | { |
340 | return insert_lookup( key ); |
341 | } |
342 | |
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 > |
361 | auto_type replace( iterator where, std::auto_ptr<U> x ) |
362 | { |
363 | return replace( where, x.release() ); |
364 | } |
365 | |
366 | protected: |
367 | 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 | |
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 > |
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: |
439 | ptr_map_adapter( ) |
440 | { } |
441 | |
442 | template< class Comp > |
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 > |
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 > |
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 > |
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 > |
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 | |
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 > |
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 > |
491 | ptr_map_adapter( std::auto_ptr<U> r ) : base_type( r ) |
492 | { } |
493 | |
494 | ptr_map_adapter& operator=( ptr_map_adapter r ) |
495 | { |
496 | this->swap( r ); |
497 | return *this; |
498 | } |
499 | |
500 | template< class U > |
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 > |
510 | void insert( InputIterator first, InputIterator last ) // basic |
511 | { |
512 | map_basic_clone_and_insert( first, last ); |
513 | } |
514 | |
515 | template< class Range > |
516 | void insert( const Range& r ) |
517 | { |
518 | insert( boost::begin(r), boost::end(r) ); |
519 | } |
520 | |
521 | private: |
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 | |
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 | |
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 > |
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 > |
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 | |
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 > |
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 > |
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 > |
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 |
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 > |
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 | |
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 > |
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( key: pair.first, |
674 | ptr: boost::ptr_container::move( ptr ) ); |
675 | // strong, commit |
676 | ++first; |
677 | } |
678 | } |
679 | |
680 | public: |
681 | |
682 | ptr_multimap_adapter() |
683 | { } |
684 | |
685 | template< class SizeType > |
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 > |
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 > |
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 > |
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 > |
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 > |
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 | |
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 > |
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 > |
740 | explicit ptr_multimap_adapter( std::auto_ptr<U> r ) : base_type( r ) |
741 | { } |
742 | |
743 | ptr_multimap_adapter& operator=( ptr_multimap_adapter r ) |
744 | { |
745 | this->swap( r ); |
746 | return *this; |
747 | } |
748 | |
749 | template< class U > |
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: |
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 | |
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 > |
786 | void insert( InputIterator first, InputIterator last ) // basic |
787 | { |
788 | map_basic_clone_and_insert( first, last ); |
789 | } |
790 | |
791 | template< class Range > |
792 | void insert( const Range& r ) |
793 | { |
794 | insert( boost::begin(r), boost::end(r) ); |
795 | } |
796 | |
797 | iterator insert( key_type& key, mapped_type x ) // strong |
798 | { |
799 | return insert_impl( key, x ); |
800 | } |
801 | |
802 | template< class U > |
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 > |
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 | |
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 > |
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 > |
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 > |
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 |
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 > |
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 > |
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 | |