]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
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( pair.first, | |
674 | 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 |