2 // Boost.Pointer Container
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)
9 // For more information, see http://www.boost.org/libs/ptr_container/
12 #ifndef BOOST_PTR_CONTAINER_DETAIL_PTR_MAP_ADAPTER_HPP
13 #define BOOST_PTR_CONTAINER_DETAIL_PTR_MAP_ADAPTER_HPP
15 #if defined(_MSC_VER) && (_MSC_VER >= 1200)
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>
27 namespace ptr_container_detail
38 typedef BOOST_DEDUCED_TYPENAME remove_nullable<T>::type
43 typedef BOOST_DEDUCED_TYPENAME VoidPtrMap::allocator_type
46 typedef BOOST_DEDUCED_TYPENAME
47 mpl::eval_if_c<Ordered,
48 select_value_compare<VoidPtrMap>,
49 mpl::identity<void> >::type
52 typedef BOOST_DEDUCED_TYPENAME
53 mpl::eval_if_c<Ordered,
54 select_key_compare<VoidPtrMap>,
55 mpl::identity<void> >::type
58 typedef BOOST_DEDUCED_TYPENAME
59 mpl::eval_if_c<Ordered,
61 select_hasher<VoidPtrMap> >::type
64 typedef BOOST_DEDUCED_TYPENAME
65 mpl::eval_if_c<Ordered,
67 select_key_equal<VoidPtrMap> >::type
70 typedef BOOST_DEDUCED_TYPENAME
72 ptr_container_detail::ordered_associative_container_tag,
73 ptr_container_detail::unordered_associative_container_tag>::type
76 typedef BOOST_DEDUCED_TYPENAME VoidPtrMap::key_type
81 typedef ptr_map_iterator< BOOST_DEDUCED_TYPENAME VoidPtrMap::iterator, key_type, U* const >
84 typedef ptr_map_iterator< BOOST_DEDUCED_TYPENAME VoidPtrMap::const_iterator, key_type, const U* const>
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,
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;
103 template< class Iter >
104 static U* get_pointer( Iter i )
109 template< class Iter >
110 static const U* get_const_pointer( Iter i )
115 BOOST_STATIC_CONSTANT( bool, allow_null = boost::is_nullable<T>::value );
124 class CloneAllocator,
127 class ptr_map_adapter_base :
128 public ptr_container_detail::associative_ptr_container< map_config<T,VoidPtrMap,Ordered>,
131 typedef ptr_container_detail::associative_ptr_container< map_config<T,VoidPtrMap,Ordered>,
135 typedef map_config<T,VoidPtrMap,Ordered> config;
136 typedef ptr_map_adapter_base<T,VoidPtrMap,CloneAllocator,Ordered> this_type;
140 typedef BOOST_DEDUCED_TYPENAME base_type::allocator_type
142 typedef BOOST_DEDUCED_TYPENAME base_type::iterator
144 typedef BOOST_DEDUCED_TYPENAME base_type::const_iterator
146 typedef BOOST_DEDUCED_TYPENAME base_type::size_type
148 typedef BOOST_DEDUCED_TYPENAME base_type::key_type
150 typedef BOOST_DEDUCED_TYPENAME base_type::auto_type
152 typedef BOOST_DEDUCED_TYPENAME base_type::value_type
154 typedef BOOST_DEDUCED_TYPENAME base_type::reference
156 typedef BOOST_DEDUCED_TYPENAME base_type::const_reference
157 const_mapped_reference;
158 typedef BOOST_DEDUCED_TYPENAME iterator_value<iterator>::type
162 typedef BOOST_DEDUCED_TYPENAME iterator_value<const_iterator>::type
166 typedef const_reference
170 const_mapped_reference lookup( const key_type& key ) const
172 const_iterator i = this->find( key );
173 BOOST_PTR_CONTAINER_THROW_EXCEPTION( i == this->end(), bad_ptr_container_operation,
174 "'ptr_map/multimap::at()' could"
179 struct eraser // scope guard
183 const key_type& key_;
185 eraser( VoidPtrMap* m, const key_type& key )
186 : released_(false), m_(m), key_(key)
195 void release() { released_ = true; }
198 eraser& operator=(const eraser&);
201 mapped_reference insert_lookup( const key_type& key )
203 void*& ref = this->base()[key];
206 return *static_cast<mapped_type>(ref);
210 eraser e(&this->base(),key); // nothrow
211 mapped_type res = new T(); // strong
212 ref = res; // nothrow
213 e.release(); // nothrow
220 ptr_map_adapter_base()
223 template< class SizeType >
224 explicit ptr_map_adapter_base( SizeType n,
225 ptr_container_detail::unordered_associative_container_tag tag )
226 : base_type( n, tag )
229 template< class Compare, class Allocator >
230 ptr_map_adapter_base( const Compare& comp,
232 : base_type( comp, a )
235 template< class Hash, class Pred, class Allocator >
236 ptr_map_adapter_base( const Hash& hash,
239 : base_type( hash, pred, a )
242 template< class InputIterator >
243 ptr_map_adapter_base( InputIterator first, InputIterator last )
244 : base_type( first, last )
247 template< class InputIterator, class Comp >
248 ptr_map_adapter_base( InputIterator first, InputIterator last,
250 const allocator_type& a = allocator_type() )
251 : base_type( first, last, comp, a )
254 template< class InputIterator, class Hash, class Pred, class Allocator >
255 ptr_map_adapter_base( InputIterator first, InputIterator last,
259 : base_type( first, last, hash, pred, a )
262 template< class PtrContainer >
263 explicit ptr_map_adapter_base( std::auto_ptr<PtrContainer> clone )
267 template< typename PtrContainer >
268 ptr_map_adapter_base& operator=( std::auto_ptr<PtrContainer> clone )
270 base_type::operator=( clone );
274 iterator find( const key_type& x )
276 return iterator( this->base().find( x ) );
279 const_iterator find( const key_type& x ) const
281 return const_iterator( this->base().find( x ) );
284 size_type count( const key_type& x ) const
286 return this->base().count( x );
289 iterator lower_bound( const key_type& x )
291 return iterator( this->base().lower_bound( x ) );
294 const_iterator lower_bound( const key_type& x ) const
296 return const_iterator( this->base().lower_bound( x ) );
299 iterator upper_bound( const key_type& x )
301 return iterator( this->base().upper_bound( x ) );
304 const_iterator upper_bound( const key_type& x ) const
306 return const_iterator( this->base().upper_bound( x ) );
309 iterator_range<iterator> equal_range( const key_type& x )
311 std::pair<BOOST_DEDUCED_TYPENAME base_type::ptr_iterator,
312 BOOST_DEDUCED_TYPENAME base_type::ptr_iterator>
313 p = this->base().equal_range( x );
314 return make_iterator_range( iterator( p.first ), iterator( p.second ) );
317 iterator_range<const_iterator> equal_range( const key_type& x ) const
319 std::pair<BOOST_DEDUCED_TYPENAME base_type::ptr_const_iterator,
320 BOOST_DEDUCED_TYPENAME base_type::ptr_const_iterator>
321 p = this->base().equal_range( x );
322 return make_iterator_range( const_iterator( p.first ),
323 const_iterator( p.second ) );
326 mapped_reference at( const key_type& key )
328 return const_cast<mapped_reference>( lookup( key ) );
331 const_mapped_reference at( const key_type& key ) const
333 return lookup( key );
336 mapped_reference operator[]( const key_type& key )
338 return insert_lookup( key );
341 auto_type replace( iterator where, mapped_type x ) // strong
343 BOOST_ASSERT( where != this->end() );
344 this->enforce_null_policy( x, "Null pointer in 'replace()'" );
346 auto_type ptr( x, *this );
347 BOOST_PTR_CONTAINER_THROW_EXCEPTION( this->empty(),
348 bad_ptr_container_operation,
349 "'replace()' on empty container" );
351 auto_type old( where->second, *this ); // nothrow
352 where.base()->second = ptr.release(); // nothrow, commit
353 return boost::ptr_container::move( old );
357 auto_type replace( iterator where, std::auto_ptr<U> x )
359 return replace( where, x.release() );
363 size_type bucket( const key_type& key ) const
365 return this->base().bucket( key );
369 } // ptr_container_detail
371 /////////////////////////////////////////////////////////////////////////
373 /////////////////////////////////////////////////////////////////////////
379 class CloneAllocator = heap_clone_allocator,
382 class ptr_map_adapter :
383 public ptr_container_detail::ptr_map_adapter_base<T,VoidPtrMap,CloneAllocator,Ordered>
385 typedef ptr_container_detail::ptr_map_adapter_base<T,VoidPtrMap,CloneAllocator,Ordered>
389 typedef BOOST_DEDUCED_TYPENAME base_type::iterator
391 typedef BOOST_DEDUCED_TYPENAME base_type::const_iterator
393 typedef BOOST_DEDUCED_TYPENAME base_type::size_type
395 typedef BOOST_DEDUCED_TYPENAME base_type::key_type
397 typedef BOOST_DEDUCED_TYPENAME base_type::const_reference
399 typedef BOOST_DEDUCED_TYPENAME base_type::auto_type
401 typedef BOOST_DEDUCED_TYPENAME VoidPtrMap::allocator_type
403 typedef BOOST_DEDUCED_TYPENAME base_type::mapped_type
407 void safe_insert( const key_type& key, auto_type ptr ) // strong
409 std::pair<BOOST_DEDUCED_TYPENAME base_type::ptr_iterator,bool>
411 this->base().insert( std::make_pair( key, ptr.get() ) ); // strong, commit
412 if( res.second ) // nothrow
413 ptr.release(); // nothrow
417 void map_basic_clone_and_insert( II first, II last )
419 while( first != last )
421 if( this->find( first->first ) == this->end() )
423 const_reference p = *first.base(); // nothrow
424 auto_type ptr( this->null_policy_allocate_clone(p.second), *this );
426 this->safe_insert( p.first,
427 boost::ptr_container::move( ptr ) );
438 template< class Comp >
439 explicit ptr_map_adapter( const Comp& comp,
440 const allocator_type& a )
441 : base_type( comp, a ) { }
443 template< class SizeType >
444 explicit ptr_map_adapter( SizeType n,
445 ptr_container_detail::unordered_associative_container_tag tag )
446 : base_type( n, tag ) { }
448 template< class Hash, class Pred, class Allocator >
449 ptr_map_adapter( const Hash& hash,
452 : base_type( hash, pred, a )
455 template< class InputIterator >
456 ptr_map_adapter( InputIterator first, InputIterator last )
458 map_basic_clone_and_insert( first, last );
461 template< class InputIterator, class Comp >
462 ptr_map_adapter( InputIterator first, InputIterator last,
464 const allocator_type& a = allocator_type() )
465 : base_type( comp, a )
467 map_basic_clone_and_insert( first, last );
470 template< class InputIterator, class Hash, class Pred, class Allocator >
471 ptr_map_adapter( InputIterator first, InputIterator last,
475 : base_type( hash, pred, a )
477 map_basic_clone_and_insert( first, last );
480 ptr_map_adapter( const ptr_map_adapter& r )
482 map_basic_clone_and_insert( r.begin(), r.end() );
485 template< class Key, class U, class CA, bool b >
486 ptr_map_adapter( const ptr_map_adapter<Key,U,CA,b>& r )
488 map_basic_clone_and_insert( r.begin(), r.end() );
492 ptr_map_adapter( std::auto_ptr<U> r ) : base_type( r )
495 ptr_map_adapter& operator=( ptr_map_adapter r )
502 ptr_map_adapter& operator=( std::auto_ptr<U> r )
504 base_type::operator=( r );
508 using base_type::release;
510 template< typename InputIterator >
511 void insert( InputIterator first, InputIterator last ) // basic
513 map_basic_clone_and_insert( first, last );
516 template< class Range >
517 void insert( const Range& r )
519 insert( boost::begin(r), boost::end(r) );
523 std::pair<iterator,bool> insert_impl( const key_type& key, mapped_type x ) // strong
525 this->enforce_null_policy( x, "Null pointer in ptr_map_adapter::insert()" );
527 auto_type ptr( x, *this ); // nothrow
528 std::pair<BOOST_DEDUCED_TYPENAME base_type::ptr_iterator,bool>
529 res = this->base().insert( std::make_pair( key, x ) ); // strong, commit
530 if( res.second ) // nothrow
531 ptr.release(); // nothrow
532 return std::make_pair( iterator( res.first ), res.second ); // nothrow
535 iterator insert_impl( iterator before, const key_type& key, mapped_type x ) // strong
537 this->enforce_null_policy( x,
538 "Null pointer in 'ptr_map_adapter::insert()'" );
540 auto_type ptr( x, *this ); // nothrow
541 BOOST_DEDUCED_TYPENAME base_type::ptr_iterator
542 res = this->base().insert( before.base(), std::make_pair( key, x ) );
544 ptr.release(); // notrow
545 return iterator( res );
550 std::pair<iterator,bool> insert( key_type& key, mapped_type x )
552 return insert_impl( key, x );
556 std::pair<iterator,bool> insert( const key_type& key, std::auto_ptr<U> x )
558 return insert_impl( key, x.release() );
561 template< class F, class S >
562 iterator insert( iterator before, ptr_container_detail::ref_pair<F,S> p ) // strong
564 this->enforce_null_policy( p.second,
565 "Null pointer in 'ptr_map_adapter::insert()'" );
567 auto_type ptr( this->null_policy_allocate_clone(p.second), *this );
568 BOOST_DEDUCED_TYPENAME base_type::ptr_iterator
569 result = this->base().insert( before.base(),
570 std::make_pair(p.first,ptr.get()) ); // strong
571 if( ptr.get() == result->second )
574 return iterator( result );
577 iterator insert( iterator before, key_type& key, mapped_type x ) // strong
579 return insert_impl( before, key, x );
583 iterator insert( iterator before, const key_type& key, std::auto_ptr<U> x ) // strong
585 return insert_impl( before, key, x.release() );
588 template< class PtrMapAdapter >
589 bool transfer( BOOST_DEDUCED_TYPENAME PtrMapAdapter::iterator object,
590 PtrMapAdapter& from ) // strong
592 return this->single_transfer( object, from );
595 template< class PtrMapAdapter >
596 size_type transfer( BOOST_DEDUCED_TYPENAME PtrMapAdapter::iterator first,
597 BOOST_DEDUCED_TYPENAME PtrMapAdapter::iterator last,
598 PtrMapAdapter& from ) // basic
600 return this->single_transfer( first, last, from );
603 #if defined(BOOST_NO_SFINAE) || defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING)
606 template< class PtrMapAdapter, class Range >
607 BOOST_DEDUCED_TYPENAME boost::disable_if< boost::is_same< Range,
608 BOOST_DEDUCED_TYPENAME PtrMapAdapter::iterator >,
610 transfer( const Range& r, PtrMapAdapter& from ) // basic
612 return transfer( boost::begin(r), boost::end(r), from );
617 template< class PtrMapAdapter >
618 size_type transfer( PtrMapAdapter& from ) // basic
620 return transfer( from.begin(), from.end(), from );
624 /////////////////////////////////////////////////////////////////////////
625 // ptr_multimap_adapter
626 /////////////////////////////////////////////////////////////////////////
631 class VoidPtrMultiMap,
632 class CloneAllocator = heap_clone_allocator,
635 class ptr_multimap_adapter :
636 public ptr_container_detail::ptr_map_adapter_base<T,VoidPtrMultiMap,CloneAllocator,Ordered>
638 typedef ptr_container_detail::ptr_map_adapter_base<T,VoidPtrMultiMap,CloneAllocator,Ordered>
642 typedef BOOST_DEDUCED_TYPENAME base_type::iterator
644 typedef BOOST_DEDUCED_TYPENAME base_type::const_iterator
646 typedef BOOST_DEDUCED_TYPENAME base_type::size_type
648 typedef BOOST_DEDUCED_TYPENAME base_type::key_type
650 typedef BOOST_DEDUCED_TYPENAME base_type::const_reference
652 typedef BOOST_DEDUCED_TYPENAME base_type::mapped_type
654 typedef BOOST_DEDUCED_TYPENAME base_type::auto_type
656 typedef BOOST_DEDUCED_TYPENAME VoidPtrMultiMap::allocator_type
660 void safe_insert( const key_type& key, auto_type ptr ) // strong
663 std::make_pair( key, ptr.get() ) ); // strong, commit
664 ptr.release(); // nothrow
667 template< typename II >
668 void map_basic_clone_and_insert( II first, II last )
670 while( first != last )
672 const_reference pair = *first.base(); // nothrow
673 auto_type ptr( this->null_policy_allocate_clone(pair.second), *this );
675 safe_insert( pair.first,
676 boost::ptr_container::move( ptr ) );
684 ptr_multimap_adapter()
687 template< class SizeType >
688 ptr_multimap_adapter( SizeType n,
689 ptr_container_detail::unordered_associative_container_tag tag )
690 : base_type( n, tag )
693 template< class Comp >
694 explicit ptr_multimap_adapter( const Comp& comp,
695 const allocator_type& a )
696 : base_type( comp, a ) { }
698 template< class Hash, class Pred, class Allocator >
699 ptr_multimap_adapter( const Hash& hash,
702 : base_type( hash, pred, a )
705 template< class InputIterator >
706 ptr_multimap_adapter( InputIterator first, InputIterator last )
708 map_basic_clone_and_insert( first, last );
711 template< class InputIterator, class Comp >
712 ptr_multimap_adapter( InputIterator first, InputIterator last,
714 const allocator_type& a )
715 : base_type( comp, a )
717 map_basic_clone_and_insert( first, last );
720 template< class InputIterator, class Hash, class Pred, class Allocator >
721 ptr_multimap_adapter( InputIterator first, InputIterator last,
725 : base_type( hash, pred, a )
727 map_basic_clone_and_insert( first, last );
730 ptr_multimap_adapter( const ptr_multimap_adapter& r )
732 map_basic_clone_and_insert( r.begin(), r.end() );
735 template< class Key, class U, class CA, bool b >
736 ptr_multimap_adapter( const ptr_multimap_adapter<Key,U,CA,b>& r )
738 map_basic_clone_and_insert( r.begin(), r.end() );
742 explicit ptr_multimap_adapter( std::auto_ptr<U> r ) : base_type( r )
745 ptr_multimap_adapter& operator=( ptr_multimap_adapter r )
752 ptr_multimap_adapter& operator=( std::auto_ptr<U> r )
754 base_type::operator=( r );
758 using base_type::release;
761 iterator insert_impl( const key_type& key, mapped_type x ) // strong
763 this->enforce_null_policy( x,
764 "Null pointer in 'ptr_multimap_adapter::insert()'" );
766 auto_type ptr( x, *this ); // nothrow
767 BOOST_DEDUCED_TYPENAME base_type::ptr_iterator
768 res = this->base().insert( std::make_pair( key, x ) );
770 ptr.release(); // notrow
771 return iterator( res );
774 iterator insert_impl( iterator before, const key_type& key, mapped_type x ) // strong
776 this->enforce_null_policy( x,
777 "Null pointer in 'ptr_multimap_adapter::insert()'" );
779 auto_type ptr( x, *this ); // nothrow
780 BOOST_DEDUCED_TYPENAME base_type::ptr_iterator
781 res = this->base().insert( before.base(),
782 std::make_pair( key, x ) );
784 ptr.release(); // notrow
785 return iterator( res );
789 template< typename InputIterator >
790 void insert( InputIterator first, InputIterator last ) // basic
792 map_basic_clone_and_insert( first, last );
795 template< class Range >
796 void insert( const Range& r )
798 insert( boost::begin(r), boost::end(r) );
801 iterator insert( key_type& key, mapped_type x ) // strong
803 return insert_impl( key, x );
807 iterator insert( const key_type& key, std::auto_ptr<U> x )
809 return insert_impl( key, x.release() );
812 template< class F, class S >
813 iterator insert( iterator before, ptr_container_detail::ref_pair<F,S> p ) // strong
815 this->enforce_null_policy( p.second,
816 "Null pointer in 'ptr_multimap_adapter::insert()'" );
817 iterator res = insert_impl( before, p.first,
818 this->null_policy_allocate_clone( p.second ) );
822 iterator insert( iterator before, key_type& key, mapped_type x ) // strong
824 return insert_impl( before, key, x );
828 iterator insert( iterator before, const key_type& key, std::auto_ptr<U> x ) // strong
830 return insert_impl( before, key, x.release() );
833 template< class PtrMapAdapter >
834 void transfer( BOOST_DEDUCED_TYPENAME PtrMapAdapter::iterator object,
835 PtrMapAdapter& from ) // strong
837 this->multi_transfer( object, from );
840 template< class PtrMapAdapter >
841 size_type transfer( BOOST_DEDUCED_TYPENAME PtrMapAdapter::iterator first,
842 BOOST_DEDUCED_TYPENAME PtrMapAdapter::iterator last,
843 PtrMapAdapter& from ) // basic
845 return this->multi_transfer( first, last, from );
848 #if defined(BOOST_NO_SFINAE) || defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING)
851 template< class PtrMapAdapter, class Range >
852 BOOST_DEDUCED_TYPENAME boost::disable_if< boost::is_same< Range,
853 BOOST_DEDUCED_TYPENAME PtrMapAdapter::iterator >,
855 transfer( const Range& r, PtrMapAdapter& from ) // basic
857 return transfer( boost::begin(r), boost::end(r), from );
861 template< class PtrMapAdapter >
862 void transfer( PtrMapAdapter& from ) // basic
864 transfer( from.begin(), from.end(), from );
865 BOOST_ASSERT( from.empty() );
870 template< class I, class F, class S >
871 inline bool is_null( const ptr_map_iterator<I,F,S>& i )
873 return i->second == 0;
876 } // namespace 'boost'