diff --git a/doc/container.qbk b/doc/container.qbk index 8e03937..6f4c114 100644 --- a/doc/container.qbk +++ b/doc/container.qbk @@ -1216,6 +1216,7 @@ use [*Boost.Container]? There are several reasons for that: [section:release_notes_boost_1_61_00 Boost 1.61 Release] * Fixed bugs: + * [@https://svn.boost.org/trac/boost/ticket/11820 Trac #11820 : ['"compilier error when using operator[] of map"]]. * [@https://svn.boost.org/trac/boost/ticket/11856 Trac #11856 : ['"pool_resource.cpp error: declaration changes meaning"]]. * [@https://github.com/boostorg/container/pull/33 GitHub #33: ['Make sure std::string constructor is available]]. diff --git a/include/boost/container/detail/node_alloc_holder.hpp b/include/boost/container/detail/node_alloc_holder.hpp index 3b632a6..1b7c4d7 100644 --- a/include/boost/container/detail/node_alloc_holder.hpp +++ b/include/boost/container/detail/node_alloc_holder.hpp @@ -60,14 +60,17 @@ struct node_alloc_holder { //If the intrusive container is an associative container, obtain the predicate, which will //be of type node_compare<>. If not an associative container value_compare will be a "nat" type. - typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_DEFAULT(boost::container::container_detail::, ICont, - value_compare, container_detail::nat) intrusive_value_compare; + typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_DEFAULT + ( boost::container::container_detail:: + , ICont, value_compare, container_detail::nat) intrusive_value_compare; //In that case obtain the value predicate from the node predicate via predicate_type //if intrusive_value_compare is node_compare<>, nat otherwise - typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_DEFAULT(boost::container::container_detail::, intrusive_value_compare, - predicate_type, container_detail::nat) value_compare; + typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_DEFAULT + ( boost::container::container_detail:: + , intrusive_value_compare + , predicate_type, container_detail::nat) value_compare; - typedef allocator_traits allocator_traits_type; + typedef allocator_traits allocator_traits_type; typedef typename allocator_traits_type::value_type value_type; typedef ICont intrusive_container; typedef typename ICont::value_type Node; @@ -75,19 +78,19 @@ struct node_alloc_holder portable_rebind_alloc::type NodeAlloc; typedef allocator_traits node_allocator_traits_type; typedef container_detail::allocator_version_traits node_allocator_version_traits_type; - typedef Allocator ValAlloc; + typedef Allocator ValAlloc; typedef typename node_allocator_traits_type::pointer NodePtr; typedef container_detail::scoped_deallocator Deallocator; typedef typename node_allocator_traits_type::size_type size_type; typedef typename node_allocator_traits_type::difference_type difference_type; typedef container_detail::integral_constant::value> alloc_version; - typedef typename ICont::iterator icont_iterator; - typedef typename ICont::const_iterator icont_citerator; - typedef allocator_destroyer Destroyer; - typedef allocator_traits NodeAllocTraits; - typedef allocator_version_traits AllocVersionTraits; + version::value> alloc_version; + typedef typename ICont::iterator icont_iterator; + typedef typename ICont::const_iterator icont_citerator; + typedef allocator_destroyer Destroyer; + typedef allocator_traits NodeAllocTraits; + typedef allocator_version_traits AllocVersionTraits; private: BOOST_COPYABLE_AND_MOVABLE(node_alloc_holder) @@ -208,6 +211,29 @@ struct node_alloc_holder return (p); } + template + NodePtr create_node_from_key(BOOST_FWD_REF(KeyConvertible) key) + { + NodePtr p = this->allocate_one(); + NodeAlloc &na = this->node_alloc(); + Deallocator node_deallocator(p, this->node_alloc()); + node_allocator_traits_type::construct + (na, container_detail::addressof(p->m_data.first), boost::forward(key)); + BOOST_TRY{ + node_allocator_traits_type::construct(na, container_detail::addressof(p->m_data.second)); + } + BOOST_CATCH(...){ + node_allocator_traits_type::destroy(na, container_detail::addressof(p->m_data.first)); + BOOST_RETHROW; + } + BOOST_CATCH_END + node_deallocator.release(); + //This does not throw + typedef typename Node::hook_type hook_type; + ::new(static_cast(container_detail::to_raw_pointer(p)), boost_container_new_t()) hook_type; + return (p); + } + void destroy_node(const NodePtr &nodep) { allocator_traits::destroy(this->node_alloc(), container_detail::to_raw_pointer(nodep)); diff --git a/include/boost/container/detail/tree.hpp b/include/boost/container/detail/tree.hpp index c2d6b1d..d039d43 100644 --- a/include/boost/container/detail/tree.hpp +++ b/include/boost/container/detail/tree.hpp @@ -1060,6 +1060,29 @@ class tree this->insert_equal(*first); } + template + iterator insert_from_key(BOOST_FWD_REF(KeyConvertible) key) + { + insert_commit_data data; + const key_type & k = key; //Support emulated rvalue references + std::pair ret = + this->icont().insert_unique_check(k, KeyNodeCompare(value_comp()), data); + return ret.second + ? this->insert_unique_key_commit(boost::forward(key), data) + : iterator(ret.first); + } + + template + iterator insert_unique_key_commit + (BOOST_FWD_REF(KeyConvertible) key, insert_commit_data &data) + { + NodePtr tmp = AllocHolder::create_node_from_key(boost::forward(key)); + scoped_destroy_deallocator destroy_deallocator(tmp, this->node_alloc()); + iterator ret(this->icont().insert_unique_commit(*tmp, data)); + destroy_deallocator.release(); + return ret; + } + iterator erase(const_iterator position) { BOOST_ASSERT(position != this->cend() && (priv_is_linked)(position)); diff --git a/include/boost/container/map.hpp b/include/boost/container/map.hpp index 8173181..2e28e70 100644 --- a/include/boost/container/map.hpp +++ b/include/boost/container/map.hpp @@ -847,31 +847,10 @@ class map #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED private: - mapped_type& priv_subscript(const key_type &k) + template + mapped_type& priv_subscript(BOOST_FWD_REF(KeyConvertible) k) { - //we can optimize this - iterator i = this->lower_bound(k); - // i->first is greater than or equivalent to k. - if (i == this->end() || this->key_comp()(k, (*i).first)){ - container_detail::value_init m; - movable_value_type val(k, boost::move(m.m_t)); - i = insert(i, boost::move(val)); - } - return (*i).second; - } - - mapped_type& priv_subscript(BOOST_RV_REF(key_type) mk) - { - key_type &k = mk; - //we can optimize this - iterator i = this->lower_bound(k); - // i->first is greater than or equivalent to k. - if (i == this->end() || this->key_comp()(k, (*i).first)){ - container_detail::value_init m; - movable_value_type val(boost::move(k), boost::move(m.m_t)); - i = insert(i, boost::move(val)); - } - return (*i).second; + return this->insert_from_key(boost::forward(k))->second; } #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED