// // Boost.Pointer Container // // Copyright Thorsten Ottosen 2003-2005. Use, modification and // distribution is subject to the Boost Software License, Version // 1.0. (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) // // For more information, see http://www.boost.org/libs/ptr_container/ // #ifndef BOOST_PTR_CONTAINER_DETAIL_PTR_MAP_ADAPTER_HPP #define BOOST_PTR_CONTAINER_DETAIL_PTR_MAP_ADAPTER_HPP #if defined(_MSC_VER) && (_MSC_VER >= 1200) # pragma once #endif #include #include #include #include #include namespace boost { namespace ptr_container_detail { template < class T, class VoidPtrMap, bool Ordered > struct map_config { typedef BOOST_DEDUCED_TYPENAME remove_nullable::type U; typedef VoidPtrMap void_container_type; typedef BOOST_DEDUCED_TYPENAME VoidPtrMap::allocator_type allocator_type; typedef BOOST_DEDUCED_TYPENAME mpl::eval_if_c, mpl::identity >::type value_compare; typedef BOOST_DEDUCED_TYPENAME mpl::eval_if_c, mpl::identity >::type key_compare; typedef BOOST_DEDUCED_TYPENAME mpl::eval_if_c, select_hasher >::type hasher; typedef BOOST_DEDUCED_TYPENAME mpl::eval_if_c, select_key_equal >::type key_equal; typedef BOOST_DEDUCED_TYPENAME mpl::if_c::type container_type; typedef BOOST_DEDUCED_TYPENAME VoidPtrMap::key_type key_type; typedef U value_type; typedef ptr_map_iterator< BOOST_DEDUCED_TYPENAME VoidPtrMap::iterator, key_type, U* const > iterator; typedef ptr_map_iterator< BOOST_DEDUCED_TYPENAME VoidPtrMap::const_iterator, key_type, const U* const> const_iterator; typedef ptr_map_iterator< BOOST_DEDUCED_TYPENAME mpl::eval_if_c, select_local_iterator >::type, key_type, U* const > local_iterator; typedef ptr_map_iterator< BOOST_DEDUCED_TYPENAME mpl::eval_if_c, select_const_local_iterator >::type, key_type, const U* const > const_local_iterator; template< class Iter > static U* get_pointer( Iter i ) { return i->second; } template< class Iter > static const U* get_const_pointer( Iter i ) { return i->second; } BOOST_STATIC_CONSTANT( bool, allow_null = boost::is_nullable::value ); }; template < class T, class VoidPtrMap, class CloneAllocator, bool Ordered > class ptr_map_adapter_base : public ptr_container_detail::associative_ptr_container< map_config, CloneAllocator > { typedef ptr_container_detail::associative_ptr_container< map_config, CloneAllocator > base_type; typedef map_config config; typedef ptr_map_adapter_base this_type; public: typedef BOOST_DEDUCED_TYPENAME base_type::allocator_type allocator_type; typedef BOOST_DEDUCED_TYPENAME base_type::iterator iterator; typedef BOOST_DEDUCED_TYPENAME base_type::const_iterator const_iterator; typedef BOOST_DEDUCED_TYPENAME base_type::size_type size_type; typedef BOOST_DEDUCED_TYPENAME base_type::key_type key_type; typedef BOOST_DEDUCED_TYPENAME base_type::auto_type auto_type; typedef BOOST_DEDUCED_TYPENAME base_type::value_type mapped_type; typedef BOOST_DEDUCED_TYPENAME base_type::reference mapped_reference; typedef BOOST_DEDUCED_TYPENAME base_type::const_reference const_mapped_reference; typedef BOOST_DEDUCED_TYPENAME iterator_value::type value_type; typedef value_type reference; typedef BOOST_DEDUCED_TYPENAME iterator_value::type const_reference; typedef value_type pointer; typedef const_reference const_pointer; private: const_mapped_reference lookup( const key_type& key ) const { const_iterator i = this->find( key ); if( i != this->end() ) return *i->second; else BOOST_PTR_CONTAINER_THROW_EXCEPTION( true, bad_ptr_container_operation, "'ptr_map/multimap::at()' could" " not find key" ); } struct eraser // scope guard { bool released_; VoidPtrMap* m_; const key_type& key_; eraser( VoidPtrMap* m, const key_type& key ) : released_(false), m_(m), key_(key) {} ~eraser() { if( !released_ ) m_->erase(key_); } void release() { released_ = true; } private: eraser& operator=(const eraser&); }; mapped_reference insert_lookup( const key_type& key ) { void*& ref = this->base()[key]; if( ref ) { return *static_cast(ref); } else { eraser e(&this->base(),key); // nothrow mapped_type res = new T(); // strong ref = res; // nothrow e.release(); // nothrow return *res; } } public: ptr_map_adapter_base() { } template< class SizeType > explicit ptr_map_adapter_base( SizeType n, ptr_container_detail::unordered_associative_container_tag tag ) : base_type( n, tag ) { } template< class Compare, class Allocator > ptr_map_adapter_base( const Compare& comp, const Allocator& a ) : base_type( comp, a ) { } template< class Hash, class Pred, class Allocator > ptr_map_adapter_base( const Hash& hash, const Pred& pred, const Allocator& a ) : base_type( hash, pred, a ) { } template< class InputIterator > ptr_map_adapter_base( InputIterator first, InputIterator last ) : base_type( first, last ) { } template< class InputIterator, class Comp > ptr_map_adapter_base( InputIterator first, InputIterator last, const Comp& comp, const allocator_type& a = allocator_type() ) : base_type( first, last, comp, a ) { } 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 ) : base_type( first, last, hash, pred, a ) { } template< class PtrContainer > explicit ptr_map_adapter_base( std::auto_ptr clone ) : base_type( clone ) { } template< typename PtrContainer > ptr_map_adapter_base& operator=( std::auto_ptr clone ) { base_type::operator=( clone ); return *this; } iterator find( const key_type& x ) { return iterator( this->base().find( x ) ); } const_iterator find( const key_type& x ) const { return const_iterator( this->base().find( x ) ); } size_type count( const key_type& x ) const { return this->base().count( x ); } iterator lower_bound( const key_type& x ) { return iterator( this->base().lower_bound( x ) ); } const_iterator lower_bound( const key_type& x ) const { return const_iterator( this->base().lower_bound( x ) ); } iterator upper_bound( const key_type& x ) { return iterator( this->base().upper_bound( x ) ); } const_iterator upper_bound( const key_type& x ) const { return const_iterator( this->base().upper_bound( x ) ); } iterator_range equal_range( const key_type& x ) { std::pair p = this->base().equal_range( x ); return make_iterator_range( iterator( p.first ), iterator( p.second ) ); } iterator_range equal_range( const key_type& x ) const { std::pair p = this->base().equal_range( x ); return make_iterator_range( const_iterator( p.first ), const_iterator( p.second ) ); } mapped_reference at( const key_type& key ) { return const_cast( lookup( key ) ); } const_mapped_reference at( const key_type& key ) const { return lookup( key ); } mapped_reference operator[]( const key_type& key ) { return insert_lookup( key ); } auto_type replace( iterator where, mapped_type x ) // strong { BOOST_ASSERT( where != this->end() ); this->enforce_null_policy( x, "Null pointer in 'replace()'" ); auto_type ptr( x ); BOOST_PTR_CONTAINER_THROW_EXCEPTION( this->empty(), bad_ptr_container_operation, "'replace()' on empty container" ); auto_type old( where->second ); // nothrow where.base()->second = ptr.release(); // nothrow, commit return boost::ptr_container::move( old ); } template< class U > auto_type replace( iterator where, std::auto_ptr x ) { return replace( where, x.release() ); } protected: size_type bucket( const key_type& key ) const { return this->base().bucket( key ); } }; } // ptr_container_detail ///////////////////////////////////////////////////////////////////////// // ptr_map_adapter ///////////////////////////////////////////////////////////////////////// template < class T, class VoidPtrMap, class CloneAllocator = heap_clone_allocator, bool Ordered = true > class ptr_map_adapter : public ptr_container_detail::ptr_map_adapter_base { typedef ptr_container_detail::ptr_map_adapter_base base_type; public: typedef BOOST_DEDUCED_TYPENAME base_type::iterator iterator; typedef BOOST_DEDUCED_TYPENAME base_type::const_iterator const_iterator; typedef BOOST_DEDUCED_TYPENAME base_type::size_type size_type; typedef BOOST_DEDUCED_TYPENAME base_type::key_type key_type; typedef BOOST_DEDUCED_TYPENAME base_type::const_reference const_reference; typedef BOOST_DEDUCED_TYPENAME base_type::auto_type auto_type; typedef BOOST_DEDUCED_TYPENAME VoidPtrMap::allocator_type allocator_type; typedef BOOST_DEDUCED_TYPENAME base_type::mapped_type mapped_type; private: void safe_insert( const key_type& key, auto_type ptr ) // strong { std::pair res = this->base().insert( std::make_pair( key, ptr.get() ) ); // strong, commit if( res.second ) // nothrow ptr.release(); // nothrow } template< class II > void map_basic_clone_and_insert( II first, II last ) { while( first != last ) { if( this->find( first->first ) == this->end() ) { const_reference p = *first.base(); // nothrow auto_type ptr( this->null_policy_allocate_clone( p.second ) ); // strong this->safe_insert( p.first, boost::ptr_container::move( ptr ) ); // strong, commit } ++first; } } public: ptr_map_adapter( ) { } template< class Comp > explicit ptr_map_adapter( const Comp& comp, const allocator_type& a ) : base_type( comp, a ) { } template< class Hash, class Pred, class Allocator > ptr_map_adapter( const Hash& hash, const Pred& pred, const Allocator& a ) : base_type( hash, pred, a ) { } template< class InputIterator > ptr_map_adapter( InputIterator first, InputIterator last ) { map_basic_clone_and_insert( first, last ); } template< class InputIterator, class Comp > ptr_map_adapter( InputIterator first, InputIterator last, const Comp& comp, const allocator_type& a = allocator_type() ) : base_type( comp, a ) { map_basic_clone_and_insert( first, last ); } 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 ) : base_type( hash, pred, a ) { map_basic_clone_and_insert( first, last ); } ptr_map_adapter( const ptr_map_adapter& r ) { map_basic_clone_and_insert( r.begin(), r.end() ); } template< class Key, class U, class CA, bool b > ptr_map_adapter( const ptr_map_adapter& r ) { map_basic_clone_and_insert( r.begin(), r.end() ); } template< class U > ptr_map_adapter( std::auto_ptr r ) : base_type( r ) { } ptr_map_adapter& operator=( ptr_map_adapter r ) { this->swap( r ); return *this; } template< class U > ptr_map_adapter& operator=( std::auto_ptr r ) { base_type::operator=( r ); return *this; } using base_type::release; template< typename InputIterator > void insert( InputIterator first, InputIterator last ) // basic { map_basic_clone_and_insert( first, last ); } template< class Range > void insert( const Range& r ) { insert( boost::begin(r), boost::end(r) ); } private: std::pair insert_impl( const key_type& key, mapped_type x ) // strong { this->enforce_null_policy( x, "Null pointer in ptr_map_adapter::insert()" ); auto_type ptr( x ); // nothrow std::pair res = this->base().insert( std::make_pair( key, x ) ); // strong, commit if( res.second ) // nothrow ptr.release(); // nothrow return std::make_pair( iterator( res.first ), res.second ); // nothrow } iterator insert_impl( iterator before, const key_type& key, mapped_type x ) // strong { this->enforce_null_policy( x, "Null pointer in 'ptr_map_adapter::insert()'" ); auto_type ptr( x ); // nothrow BOOST_DEDUCED_TYPENAME base_type::ptr_iterator res = this->base().insert( before.base(), std::make_pair( key, x ) ); // strong, commit ptr.release(); // notrow return iterator( res ); } public: std::pair insert( key_type& key, mapped_type x ) { return insert_impl( key, x ); } template< class U > std::pair insert( const key_type& key, std::auto_ptr x ) { return insert_impl( key, x.release() ); } template< class F, class S > iterator insert( iterator before, ptr_container_detail::ref_pair p ) // strong { this->enforce_null_policy( p.second, "Null pointer in 'ptr_map_adapter::insert()'" ); auto_type ptr( this->null_policy_allocate_clone( p.second ) ); BOOST_DEDUCED_TYPENAME base_type::ptr_iterator result = this->base().insert( before.base(), std::make_pair(p.first,ptr.get()) ); // strong if( ptr.get() == result->second ) ptr.release(); return iterator( result ); } iterator insert( iterator before, key_type& key, mapped_type x ) // strong { return insert_impl( before, key, x ); } template< class U > iterator insert( iterator before, const key_type& key, std::auto_ptr x ) // strong { return insert_impl( before, key, x.release() ); } template< class PtrMapAdapter > bool transfer( BOOST_DEDUCED_TYPENAME PtrMapAdapter::iterator object, PtrMapAdapter& from ) // strong { return this->single_transfer( object, from ); } template< class PtrMapAdapter > size_type transfer( BOOST_DEDUCED_TYPENAME PtrMapAdapter::iterator first, BOOST_DEDUCED_TYPENAME PtrMapAdapter::iterator last, PtrMapAdapter& from ) // basic { return this->single_transfer( first, last, from ); } #if defined(BOOST_NO_SFINAE) || defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING) #else template< class PtrMapAdapter, class Range > BOOST_DEDUCED_TYPENAME boost::disable_if< boost::is_same< Range, BOOST_DEDUCED_TYPENAME PtrMapAdapter::iterator >, size_type >::type transfer( const Range& r, PtrMapAdapter& from ) // basic { return transfer( boost::begin(r), boost::end(r), from ); } #endif template< class PtrMapAdapter > size_type transfer( PtrMapAdapter& from ) // basic { return transfer( from.begin(), from.end(), from ); } }; ///////////////////////////////////////////////////////////////////////// // ptr_multimap_adapter ///////////////////////////////////////////////////////////////////////// template < class T, class VoidPtrMultiMap, class CloneAllocator = heap_clone_allocator, bool Ordered = true > class ptr_multimap_adapter : public ptr_container_detail::ptr_map_adapter_base { typedef ptr_container_detail::ptr_map_adapter_base base_type; public: // typedefs typedef BOOST_DEDUCED_TYPENAME base_type::iterator iterator; typedef BOOST_DEDUCED_TYPENAME base_type::const_iterator const_iterator; typedef BOOST_DEDUCED_TYPENAME base_type::size_type size_type; typedef BOOST_DEDUCED_TYPENAME base_type::key_type key_type; typedef BOOST_DEDUCED_TYPENAME base_type::const_reference const_reference; typedef BOOST_DEDUCED_TYPENAME base_type::mapped_type mapped_type; typedef BOOST_DEDUCED_TYPENAME base_type::auto_type auto_type; typedef BOOST_DEDUCED_TYPENAME VoidPtrMultiMap::allocator_type allocator_type; private: void safe_insert( const key_type& key, auto_type ptr ) // strong { this->base().insert( std::make_pair( key, ptr.get() ) ); // strong, commit ptr.release(); // nothrow } template< typename II > void map_basic_clone_and_insert( II first, II last ) { while( first != last ) { const_reference pair = *first.base(); // nothrow auto_type ptr( this->null_policy_allocate_clone( pair.second ) ); // strong safe_insert( pair.first, boost::ptr_container::move( ptr ) ); // strong, commit ++first; } } public: ptr_multimap_adapter() { } template< class SizeType > ptr_multimap_adapter( SizeType n, ptr_container_detail::unordered_associative_container_tag tag ) : base_type( n, tag ) { } template< class Comp > explicit ptr_multimap_adapter( const Comp& comp, const allocator_type& a ) : base_type( comp, a ) { } template< class Hash, class Pred, class Allocator > ptr_multimap_adapter( const Hash& hash, const Pred& pred, const Allocator& a ) : base_type( hash, pred, a ) { } template< class InputIterator > ptr_multimap_adapter( InputIterator first, InputIterator last ) { map_basic_clone_and_insert( first, last ); } template< class InputIterator, class Comp > ptr_multimap_adapter( InputIterator first, InputIterator last, const Comp& comp, const allocator_type& a ) : base_type( comp, a ) { map_basic_clone_and_insert( first, last ); } 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 ) : base_type( hash, pred, a ) { map_basic_clone_and_insert( first, last ); } ptr_multimap_adapter( const ptr_multimap_adapter& r ) { map_basic_clone_and_insert( r.begin(), r.end() ); } template< class Key, class U, class CA, bool b > ptr_multimap_adapter( const ptr_multimap_adapter& r ) { map_basic_clone_and_insert( r.begin(), r.end() ); } template< class U > explicit ptr_multimap_adapter( std::auto_ptr r ) : base_type( r ) { } ptr_multimap_adapter& operator=( ptr_multimap_adapter r ) { this->swap( r ); return *this; } template< class U > ptr_multimap_adapter& operator=( std::auto_ptr r ) { base_type::operator=( r ); return *this; } using base_type::release; private: iterator insert_impl( const key_type& key, mapped_type x ) // strong { this->enforce_null_policy( x, "Null pointer in 'ptr_multimap_adapter::insert()'" ); auto_type ptr( x ); // nothrow BOOST_DEDUCED_TYPENAME base_type::ptr_iterator res = this->base().insert( std::make_pair( key, x ) ); // strong, commit ptr.release(); // notrow return iterator( res ); } iterator insert_impl( iterator before, const key_type& key, mapped_type x ) // strong { this->enforce_null_policy( x, "Null pointer in 'ptr_multimap_adapter::insert()'" ); auto_type ptr( x ); // nothrow BOOST_DEDUCED_TYPENAME base_type::ptr_iterator res = this->base().insert( before.base(), std::make_pair( key, x ) ); // strong, commit ptr.release(); // notrow return iterator( res ); } public: template< typename InputIterator > void insert( InputIterator first, InputIterator last ) // basic { map_basic_clone_and_insert( first, last ); } template< class Range > void insert( const Range& r ) { insert( boost::begin(r), boost::end(r) ); } iterator insert( key_type& key, mapped_type x ) // strong { return insert_impl( key, x ); } template< class U > iterator insert( const key_type& key, std::auto_ptr x ) { return insert_impl( key, x.release() ); } template< class F, class S > iterator insert( iterator before, ptr_container_detail::ref_pair p ) // strong { this->enforce_null_policy( p.second, "Null pointer in 'ptr_multimap_adapter::insert()'" ); iterator res = insert_impl( before, p.first, this->null_policy_allocate_clone( p.second ) ); return res; } iterator insert( iterator before, key_type& key, mapped_type x ) // strong { return insert_impl( before, key, x ); } template< class U > iterator insert( iterator before, const key_type& key, std::auto_ptr x ) // strong { return insert_impl( before, key, x.release() ); } template< class PtrMapAdapter > void transfer( BOOST_DEDUCED_TYPENAME PtrMapAdapter::iterator object, PtrMapAdapter& from ) // strong { this->multi_transfer( object, from ); } template< class PtrMapAdapter > size_type transfer( BOOST_DEDUCED_TYPENAME PtrMapAdapter::iterator first, BOOST_DEDUCED_TYPENAME PtrMapAdapter::iterator last, PtrMapAdapter& from ) // basic { return this->multi_transfer( first, last, from ); } #if defined(BOOST_NO_SFINAE) || defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING) #else template< class PtrMapAdapter, class Range > BOOST_DEDUCED_TYPENAME boost::disable_if< boost::is_same< Range, BOOST_DEDUCED_TYPENAME PtrMapAdapter::iterator >, size_type >::type transfer( const Range& r, PtrMapAdapter& from ) // basic { return transfer( boost::begin(r), boost::end(r), from ); } #endif template< class PtrMapAdapter > void transfer( PtrMapAdapter& from ) // basic { transfer( from.begin(), from.end(), from ); BOOST_ASSERT( from.empty() ); } }; template< class I, class F, class S > inline bool is_null( const ptr_map_iterator& i ) { return i->second == 0; } } // namespace 'boost' #endif