diff --git a/doc/container.qbk b/doc/container.qbk index d2ba3db..91cdbc8 100644 --- a/doc/container.qbk +++ b/doc/container.qbk @@ -1347,6 +1347,7 @@ use [*Boost.Container]? There are several reasons for that: standard exception classes, you can define `BOOST_CONTAINER_USE_STD_EXCEPTIONS` before using any Boost.Container class. * Fixed bugs/issues: + * [@https://github.com/boostorg/container/issues/102 GitHub #102: ['"flat_map::insert ambiguous with initializer list & pairs that need to convert"]]. * [@https://github.com/boostorg/container/issues/139 GitHub #139: ['"flat_map merge and iterators"]]. * [@https://github.com/boostorg/container/issues/141 GitHub #141: ['"small_vector does not propagate no throw properties of move operation of contained type"]]. * [@https://github.com/boostorg/container/issues/164 GitHub #164: ['"Compile error when using `pmr::map` with a `std::pair`; works when using a `std::tuple`"]]. diff --git a/include/boost/container/detail/tree.hpp b/include/boost/container/detail/tree.hpp index a4b99fd..14a1f15 100644 --- a/include/boost/container/detail/tree.hpp +++ b/include/boost/container/detail/tree.hpp @@ -670,7 +670,7 @@ class tree if(unique_insertion){ const const_iterator end_it(this->cend()); for ( ; first != last; ++first){ - this->insert_unique_convertible(end_it, *first); + this->insert_unique_hint_convertible(end_it, *first); } } else{ @@ -694,7 +694,7 @@ class tree //for the constructor const const_iterator end_it(this->cend()); for ( ; first != last; ++first){ - this->insert_equal_convertible(end_it, *first); + this->insert_equal_hint_convertible(end_it, *first); } } @@ -1006,7 +1006,7 @@ class tree } template - std::pair insert_unique(BOOST_FWD_REF(MovableConvertible) v) + std::pair insert_unique_convertible(BOOST_FWD_REF(MovableConvertible) v) { insert_commit_data data; std::pair ret = @@ -1017,6 +1017,19 @@ class tree return ret; } + template + iterator insert_unique_hint_convertible(const_iterator hint, BOOST_FWD_REF(MovableConvertible) v) + { + BOOST_ASSERT((priv_is_linked)(hint)); + insert_commit_data data; + std::pair ret = + this->insert_unique_check(hint, key_of_value_t()(v), data); + if(!ret.second) + return ret.first; + return this->insert_unique_commit(boost::forward(v), data); + } + + private: template @@ -1047,7 +1060,7 @@ class tree this->icont().push_back(*tmp); } - std::pair emplace_unique_impl(NodePtr p) + std::pair emplace_unique_node(NodePtr p) { value_type &v = p->get_data(); insert_commit_data data; @@ -1064,7 +1077,7 @@ class tree , true ); } - iterator emplace_unique_hint_impl(const_iterator hint, NodePtr p) + iterator emplace_hint_unique_node(const_iterator hint, NodePtr p) { BOOST_ASSERT((priv_is_linked)(hint)); value_type &v = p->get_data(); @@ -1072,6 +1085,7 @@ class tree std::pair ret = this->insert_unique_check(hint, key_of_value_t()(v), data); if(!ret.second){ + //Destroy unneeded node Destroyer(this->node_alloc())(p); return ret.first; } @@ -1084,11 +1098,11 @@ class tree template BOOST_CONTAINER_FORCEINLINE std::pair emplace_unique(BOOST_FWD_REF(Args)... args) - { return this->emplace_unique_impl(AllocHolder::create_node(boost::forward(args)...)); } + { return this->emplace_unique_node(AllocHolder::create_node(boost::forward(args)...)); } template BOOST_CONTAINER_FORCEINLINE iterator emplace_hint_unique(const_iterator hint, BOOST_FWD_REF(Args)... args) - { return this->emplace_unique_hint_impl(hint, AllocHolder::create_node(boost::forward(args)...)); } + { return this->emplace_hint_unique_node(hint, AllocHolder::create_node(boost::forward(args)...)); } template iterator emplace_equal(BOOST_FWD_REF(Args)... args) @@ -1132,11 +1146,11 @@ class tree #define BOOST_CONTAINER_TREE_EMPLACE_CODE(N) \ BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \ std::pair emplace_unique(BOOST_MOVE_UREF##N)\ - { return this->emplace_unique_impl(AllocHolder::create_node(BOOST_MOVE_FWD##N)); }\ + { return this->emplace_unique_node(AllocHolder::create_node(BOOST_MOVE_FWD##N)); }\ \ BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \ iterator emplace_hint_unique(const_iterator hint BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\ - { return this->emplace_unique_hint_impl(hint, AllocHolder::create_node(BOOST_MOVE_FWD##N)); }\ + { return this->emplace_hint_unique_node(hint, AllocHolder::create_node(BOOST_MOVE_FWD##N)); }\ \ BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \ iterator emplace_equal(BOOST_MOVE_UREF##N)\ @@ -1180,38 +1194,17 @@ class tree #endif // !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) - template - iterator insert_unique_convertible(const_iterator hint, BOOST_FWD_REF(MovableConvertible) v) - { - BOOST_ASSERT((priv_is_linked)(hint)); - insert_commit_data data; - std::pair ret = - this->insert_unique_check(hint, key_of_value_t()(v), data); - if(!ret.second) - return ret.first; - return this->insert_unique_commit(boost::forward(v), data); - } - - BOOST_MOVE_CONVERSION_AWARE_CATCH_1ARG(insert_unique, value_type, iterator, this->insert_unique_convertible, const_iterator, const_iterator) + //BOOST_MOVE_CONVERSION_AWARE_CATCH_1ARG(insert_unique, value_type, iterator, this->insert_unique_hint_convertible, const_iterator, const_iterator) template - void insert_unique(InputIterator first, InputIterator last) + void insert_unique_range(InputIterator first, InputIterator last) { for( ; first != last; ++first) - this->insert_unique(*first); - } - - iterator insert_equal(const value_type& v) - { - NodePtr tmp(AllocHolder::create_node(v)); - scoped_destroy_deallocator destroy_deallocator(tmp, this->node_alloc()); - iterator ret(this->icont().insert_equal(this->icont().end(), *tmp)); - destroy_deallocator.release(); - return ret; + this->insert_unique_convertible(*first); } template - iterator insert_equal(BOOST_FWD_REF(MovableConvertible) v) + iterator insert_equal_convertible(BOOST_FWD_REF(MovableConvertible) v) { NodePtr tmp(AllocHolder::create_node(boost::forward(v))); scoped_destroy_deallocator destroy_deallocator(tmp, this->node_alloc()); @@ -1221,7 +1214,7 @@ class tree } template - iterator insert_equal_convertible(const_iterator hint, BOOST_FWD_REF(MovableConvertible) v) + iterator insert_equal_hint_convertible(const_iterator hint, BOOST_FWD_REF(MovableConvertible) v) { BOOST_ASSERT((priv_is_linked)(hint)); NodePtr tmp(AllocHolder::create_node(boost::forward(v))); @@ -1231,13 +1224,14 @@ class tree return ret; } - BOOST_MOVE_CONVERSION_AWARE_CATCH_1ARG(insert_equal, value_type, iterator, this->insert_equal_convertible, const_iterator, const_iterator) + BOOST_MOVE_CONVERSION_AWARE_CATCH_1ARG + (insert_equal, value_type, iterator, this->insert_equal_hint_convertible, const_iterator, const_iterator) template - void insert_equal(InputIterator first, InputIterator last) + void insert_equal_range(InputIterator first, InputIterator last) { for( ; first != last; ++first) - this->insert_equal(*first); + this->insert_equal_convertible(*first); } template diff --git a/include/boost/container/detail/type_traits.hpp b/include/boost/container/detail/type_traits.hpp index b5250d6..0c4f982 100644 --- a/include/boost/container/detail/type_traits.hpp +++ b/include/boost/container/detail/type_traits.hpp @@ -65,6 +65,7 @@ using ::boost::move_detail::nat; using ::boost::move_detail::nat2; using ::boost::move_detail::nat3; using ::boost::move_detail::max_align_t; +using ::boost::move_detail::is_convertible; } //namespace dtl { } //namespace container { diff --git a/include/boost/container/flat_map.hpp b/include/boost/container/flat_map.hpp index 4cf41af..101a9d5 100644 --- a/include/boost/container/flat_map.hpp +++ b/include/boost/container/flat_map.hpp @@ -1077,10 +1077,12 @@ class flat_map //! //! Note: If an element is inserted it might invalidate elements. BOOST_CONTAINER_FORCEINLINE std::pair insert(BOOST_RV_REF(value_type) x) - { return dtl::force_copy >( - m_flat_tree.insert_unique(boost::move(dtl::force(x)))); } + { + return dtl::force_copy >( + m_flat_tree.insert_unique(boost::move(dtl::force(x)))); + } - //! Effects: Inserts a new value_type move constructed from the pair if and + //! Effects: Inserts a new value_type constructed from the pair if and //! only if there is no element in the container with key equivalent to the key of x. //! //! Returns: The bool component of the returned pair is true if and only @@ -1091,10 +1093,15 @@ class flat_map //! to the elements with bigger keys than x. //! //! Note: If an element is inserted it might invalidate elements. - BOOST_CONTAINER_FORCEINLINE std::pair insert(BOOST_RV_REF(movable_value_type) x) + template + BOOST_CONTAINER_FORCEINLINE BOOST_CONTAINER_DOC1ST + ( std::pair + , typename dtl::enable_if_c::value + BOOST_MOVE_I std::pair >::type) + insert(BOOST_FWD_REF(Pair) x) { return dtl::force_copy > - (m_flat_tree.insert_unique(boost::move(x))); + (m_flat_tree.emplace_unique(boost::forward(x))); } //! Effects: Inserts a copy of x in the container if and only if there is @@ -1131,7 +1138,7 @@ class flat_map , boost::move(dtl::force(x)))); } - //! Effects: Inserts an element move constructed from x in the container. + //! Effects: Inserts an element constructed from x in the container. //! p is a hint pointing to where the insert should start to search. //! //! Returns: An iterator pointing to the element with key equivalent to the key of x. @@ -1140,10 +1147,15 @@ class flat_map //! right before p) plus insertion linear to the elements with bigger keys than x. //! //! Note: If an element is inserted it might invalidate elements. - BOOST_CONTAINER_FORCEINLINE iterator insert(const_iterator p, BOOST_RV_REF(movable_value_type) x) + template + BOOST_CONTAINER_FORCEINLINE BOOST_CONTAINER_DOC1ST + ( iterator + , typename dtl::enable_if_c::value + BOOST_MOVE_I iterator>::type) + insert(const_iterator p, BOOST_FWD_REF(Pair) x) { return dtl::force_copy( - m_flat_tree.insert_unique(dtl::force_copy(p), boost::move(x))); + m_flat_tree.emplace_hint_unique(dtl::force_copy(p), boost::forward(x))); } //! Requires: first, last are not iterators into *this. @@ -1608,22 +1620,24 @@ class flat_map private: mapped_type &priv_subscript(const key_type& k) { - iterator i = lower_bound(k); + iterator i = this->lower_bound(k); // i->first is greater than or equivalent to k. if (i == end() || key_comp()(k, (*i).first)){ dtl::value_init m; - i = insert(i, impl_value_type(k, ::boost::move(m.m_t))); + impl_value_type v(k, ::boost::move(m.m_t)); + i = this->insert(i, ::boost::move(v)); } return (*i).second; } mapped_type &priv_subscript(BOOST_RV_REF(key_type) mk) { key_type &k = mk; - iterator i = lower_bound(k); + iterator i = this->lower_bound(k); // i->first is greater than or equivalent to k. if (i == end() || key_comp()(k, (*i).first)){ dtl::value_init m; - i = insert(i, impl_value_type(boost::move(k), ::boost::move(m.m_t))); + impl_value_type v(::boost::move(k), ::boost::move(m.m_t)); + i = this->insert(i, ::boost::move(v)); } return (*i).second; } @@ -2441,25 +2455,20 @@ class flat_multimap m_flat_tree.insert_equal(dtl::force(x))); } - //! Effects: Inserts a new value move-constructed from x and returns + //! Effects: Inserts a new value constructed from x and returns //! the iterator pointing to the newly inserted element. //! //! Complexity: Logarithmic search time plus linear insertion //! to the elements with bigger keys than x. //! //! Note: If an element is inserted it might invalidate elements. - BOOST_CONTAINER_FORCEINLINE iterator insert(BOOST_RV_REF(value_type) x) - { return dtl::force_copy(m_flat_tree.insert_equal(boost::move(x))); } - - //! Effects: Inserts a new value move-constructed from x and returns - //! the iterator pointing to the newly inserted element. - //! - //! Complexity: Logarithmic search time plus linear insertion - //! to the elements with bigger keys than x. - //! - //! Note: If an element is inserted it might invalidate elements. - BOOST_CONTAINER_FORCEINLINE iterator insert(BOOST_RV_REF(impl_value_type) x) - { return dtl::force_copy(m_flat_tree.insert_equal(boost::move(x))); } + template + BOOST_CONTAINER_FORCEINLINE BOOST_CONTAINER_DOC1ST + ( iterator + , typename dtl::enable_if_c::value + BOOST_MOVE_I iterator >::type) + insert(BOOST_FWD_REF(Pair) x) + { return dtl::force_copy(m_flat_tree.emplace_equal(boost::forward(x))); } //! Effects: Inserts a copy of x in the container. //! p is a hint pointing to where the insert should start to search. @@ -2479,7 +2488,7 @@ class flat_multimap , dtl::force(x))); } - //! Effects: Inserts a value move constructed from x in the container. + //! Effects: Inserts a value constructed from x in the container. //! p is a hint pointing to where the insert should start to search. //! //! Returns: An iterator pointing to the element with key equivalent @@ -2490,28 +2499,15 @@ class flat_multimap //! to the elements with bigger keys than x. //! //! Note: If an element is inserted it might invalidate elements. - BOOST_CONTAINER_FORCEINLINE iterator insert(const_iterator p, BOOST_RV_REF(value_type) x) - { - return dtl::force_copy - (m_flat_tree.insert_equal(dtl::force_copy(p) - , boost::move(x))); - } - - //! Effects: Inserts a value move constructed from x in the container. - //! p is a hint pointing to where the insert should start to search. - //! - //! Returns: An iterator pointing to the element with key equivalent - //! to the key of x. - //! - //! Complexity: Logarithmic search time (constant time if the value - //! is to be inserted before p) plus linear insertion - //! to the elements with bigger keys than x. - //! - //! Note: If an element is inserted it might invalidate elements. - BOOST_CONTAINER_FORCEINLINE iterator insert(const_iterator p, BOOST_RV_REF(impl_value_type) x) + template + BOOST_CONTAINER_FORCEINLINE BOOST_CONTAINER_DOC1ST + ( iterator + , typename dtl::enable_if_c::value + BOOST_MOVE_I iterator>::type) + insert(const_iterator p, BOOST_FWD_REF(Pair) x) { return dtl::force_copy( - m_flat_tree.insert_equal(dtl::force_copy(p), boost::move(x))); + m_flat_tree.emplace_hint_equal(dtl::force_copy(p), boost::forward(x))); } //! Requires: first, last are not iterators into *this. diff --git a/include/boost/container/flat_set.hpp b/include/boost/container/flat_set.hpp index 7af8395..6b3f50c 100644 --- a/include/boost/container/flat_set.hpp +++ b/include/boost/container/flat_set.hpp @@ -667,7 +667,7 @@ class flat_set private: typedef std::pair insert_return_pair; public: - BOOST_MOVE_CONVERSION_AWARE_CATCH(insert, value_type, insert_return_pair, this->priv_insert) + BOOST_MOVE_CONVERSION_AWARE_CATCH(insert, value_type, insert_return_pair, this->tree_t::insert_unique) #endif #if defined(BOOST_CONTAINER_DOXYGEN_INVOKED) @@ -695,7 +695,7 @@ class flat_set //! Note: If an element is inserted it might invalidate elements. iterator insert(const_iterator p, value_type &&x); #else - BOOST_MOVE_CONVERSION_AWARE_CATCH_1ARG(insert, value_type, iterator, this->priv_insert, const_iterator, const_iterator) + BOOST_MOVE_CONVERSION_AWARE_CATCH_1ARG(insert, value_type, iterator, this->tree_t::insert_unique, const_iterator, const_iterator) #endif //! Requires: first, last are not iterators into *this. @@ -1117,17 +1117,6 @@ class flat_set //! Throws: If the move assignment throws BOOST_CONTAINER_FORCEINLINE void adopt_sequence(ordered_unique_range_t, BOOST_RV_REF(sequence_type) seq) { this->tree_t::adopt_sequence_unique(ordered_unique_range_t(), boost::move(seq)); } - - #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED - private: - template - BOOST_CONTAINER_FORCEINLINE std::pair priv_insert(BOOST_FWD_REF(KeyType) x) - { return this->tree_t::insert_unique(::boost::forward(x)); } - - template - BOOST_CONTAINER_FORCEINLINE iterator priv_insert(const_iterator p, BOOST_FWD_REF(KeyType) x) - { return this->tree_t::insert_unique(p, ::boost::forward(x)); } - #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED }; #ifndef BOOST_CONTAINER_NO_CXX17_CTAD @@ -1617,7 +1606,7 @@ class flat_multiset //! Note: If an element is inserted it might invalidate elements. iterator insert(value_type &&x); #else - BOOST_MOVE_CONVERSION_AWARE_CATCH(insert, value_type, iterator, this->priv_insert) + BOOST_MOVE_CONVERSION_AWARE_CATCH(insert, value_type, iterator, this->tree_t::insert_equal) #endif #if defined(BOOST_CONTAINER_DOXYGEN_INVOKED) @@ -1645,7 +1634,7 @@ class flat_multiset //! Note: If an element is inserted it might invalidate elements. iterator insert(const_iterator p, value_type &&x); #else - BOOST_MOVE_CONVERSION_AWARE_CATCH_1ARG(insert, value_type, iterator, this->priv_insert, const_iterator, const_iterator) + BOOST_MOVE_CONVERSION_AWARE_CATCH_1ARG(insert, value_type, iterator, this->tree_t::insert_equal, const_iterator, const_iterator) #endif //! Requires: first, last are not iterators into *this. @@ -1849,17 +1838,6 @@ class flat_multiset //! Throws: If the move assignment throws BOOST_CONTAINER_FORCEINLINE void adopt_sequence(ordered_range_t, BOOST_RV_REF(sequence_type) seq) { this->tree_t::adopt_sequence_equal(ordered_range_t(), boost::move(seq)); } - - #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED - private: - template - BOOST_CONTAINER_FORCEINLINE iterator priv_insert(BOOST_FWD_REF(KeyType) x) - { return this->tree_t::insert_equal(::boost::forward(x)); } - - template - BOOST_CONTAINER_FORCEINLINE iterator priv_insert(const_iterator p, BOOST_FWD_REF(KeyType) x) - { return this->tree_t::insert_equal(p, ::boost::forward(x)); } - #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED }; #ifndef BOOST_CONTAINER_NO_CXX17_CTAD diff --git a/include/boost/container/map.hpp b/include/boost/container/map.hpp index 84270e9..ac7abe0 100644 --- a/include/boost/container/map.hpp +++ b/include/boost/container/map.hpp @@ -121,7 +121,7 @@ class map typedef typename BOOST_CONTAINER_IMPDEF(base_t::const_iterator) const_iterator; typedef typename BOOST_CONTAINER_IMPDEF(base_t::reverse_iterator) reverse_iterator; typedef typename BOOST_CONTAINER_IMPDEF(base_t::const_reverse_iterator) const_reverse_iterator; - typedef std::pair nonconst_value_type; + //typedef std::pair nonconst_value_type; typedef BOOST_CONTAINER_IMPDEF(movable_value_type_impl) movable_value_type; typedef BOOST_CONTAINER_IMPDEF(node_handle< typename base_t::stored_allocator_type @@ -688,40 +688,7 @@ class map //! //! Complexity: Logarithmic. BOOST_CONTAINER_FORCEINLINE std::pair insert(const value_type& x) - { return this->base_t::insert_unique(x); } - - //! Effects: Inserts a new value_type created from the pair if and only if - //! there is no element in the container with key equivalent to the key of x. - //! - //! Returns: The bool component of the returned pair is true if and only - //! if the insertion takes place, and the iterator component of the pair - //! points to the element with key equivalent to the key of x. - //! - //! Complexity: Logarithmic. - BOOST_CONTAINER_FORCEINLINE std::pair insert(const nonconst_value_type& x) - { return this->try_emplace(x.first, x.second); } - - //! Effects: Inserts a new value_type move constructed from the pair if and - //! only if there is no element in the container with key equivalent to the key of x. - //! - //! Returns: The bool component of the returned pair is true if and only - //! if the insertion takes place, and the iterator component of the pair - //! points to the element with key equivalent to the key of x. - //! - //! Complexity: Logarithmic. - BOOST_CONTAINER_FORCEINLINE std::pair insert(BOOST_RV_REF(nonconst_value_type) x) - { return this->try_emplace(boost::move(x.first), boost::move(x.second)); } - - //! Effects: Inserts a new value_type move constructed from the pair if and - //! only if there is no element in the container with key equivalent to the key of x. - //! - //! Returns: The bool component of the returned pair is true if and only - //! if the insertion takes place, and the iterator component of the pair - //! points to the element with key equivalent to the key of x. - //! - //! Complexity: Logarithmic. - BOOST_CONTAINER_FORCEINLINE std::pair insert(BOOST_RV_REF(movable_value_type) x) - { return this->try_emplace(boost::move(x.first), boost::move(x.second)); } + { return this->base_t::insert_unique_convertible(x); } //! Effects: Move constructs a new value from x if and only if there is //! no element in the container with key equivalent to the key of x. @@ -732,7 +699,28 @@ class map //! //! Complexity: Logarithmic. BOOST_CONTAINER_FORCEINLINE std::pair insert(BOOST_RV_REF(value_type) x) - { return this->base_t::insert_unique(boost::move(x)); } + { return this->base_t::insert_unique_convertible(boost::move(x)); } + + //! Effects: Inserts a new value_type created from the pair if and only if + //! there is no element in the container with key equivalent to the key of x. + //! + //! Returns: The bool component of the returned pair is true if and only + //! if the insertion takes place, and the iterator component of the pair + //! points to the element with key equivalent to the key of x. + //! + //! Complexity: Logarithmic. + template + BOOST_CONTAINER_FORCEINLINE BOOST_CONTAINER_DOC1ST + ( std::pair + , typename dtl::enable_if_c< + dtl::is_convertible::value || + dtl::is_convertible::value + BOOST_MOVE_I std::pair >::type) + insert(BOOST_FWD_REF(Pair) x) + { return this->base_t::emplace_unique(boost::forward(x)); } + + BOOST_CONTAINER_FORCEINLINE iterator insert(const_iterator p, const value_type& x) + { return this->base_t::insert_unique_hint_convertible(p, x); } //! Effects: Inserts a copy of x in the container if and only if there is //! no element in the container with key equivalent to the key of x. @@ -743,9 +731,30 @@ class map //! //! Complexity: Logarithmic in general, but amortized constant if t //! is inserted right before p. - BOOST_CONTAINER_FORCEINLINE iterator insert(const_iterator p, const value_type& x) - { return this->base_t::insert_unique(p, x); } + BOOST_CONTAINER_FORCEINLINE iterator insert(const_iterator p, BOOST_RV_REF(value_type) x) + { return this->base_t::insert_unique_hint_convertible(p, boost::move(x)); } + //! Effects: Inserts a copy of x in the container if and only if there is + //! no element in the container with key equivalent to the key of x. + //! p is a hint pointing to where the insert should start to search. + //! + //! Returns: An iterator pointing to the element with key equivalent + //! to the key of x. + //! + //! Complexity: Logarithmic in general, but amortized constant if t + //! is inserted right before p. + template + BOOST_CONTAINER_FORCEINLINE BOOST_CONTAINER_DOC1ST + ( iterator + , typename dtl::enable_if_c< + dtl::is_convertible::value || + dtl::is_convertible::value + BOOST_MOVE_I iterator >::type) + insert(const_iterator p, BOOST_FWD_REF(Pair) x) + { return this->base_t::emplace_hint_unique(p, boost::forward(x)); } + + +/* //! Effects: Move constructs a new value from x if and only if there is //! no element in the container with key equivalent to the key of x. //! p is a hint pointing to where the insert should start to search. @@ -776,18 +785,11 @@ class map //! Returns: An iterator pointing to the element with key equivalent to the key of x. //! //! Complexity: Logarithmic. - iterator insert(const_iterator p, const nonconst_value_type& x) + BOOST_CONTAINER_FORCEINLINE iterator insert(const_iterator p, const nonconst_value_type& x) { return this->try_emplace(p, x.first, x.second); } - //! Effects: Inserts an element move constructed from x in the container. - //! p is a hint pointing to where the insert should start to search. - //! - //! Returns: An iterator pointing to the element with key equivalent to the key of x. - //! - //! Complexity: Logarithmic. - BOOST_CONTAINER_FORCEINLINE iterator insert(const_iterator p, BOOST_RV_REF(value_type) x) - { return this->base_t::insert_unique(p, boost::move(x)); } +*/ //! Requires: first, last are not iterators into *this. //! //! Effects: inserts each element from the range [first,last) if and only @@ -796,7 +798,7 @@ class map //! Complexity: At most N log(size()+N) (N is the distance from first to last) template BOOST_CONTAINER_FORCEINLINE void insert(InputIterator first, InputIterator last) - { this->base_t::insert_unique(first, last); } + { this->base_t::insert_unique_range(first, last); } #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) //! Effects: inserts each element from the range [il.begin(), il.end()) if and only @@ -804,7 +806,7 @@ class map //! //! Complexity: At most N log(size()+N) (N is the distance from il.begin() to il.end()) BOOST_CONTAINER_FORCEINLINE void insert(std::initializer_list il) - { this->base_t::insert_unique(il.begin(), il.end()); } + { this->base_t::insert_unique_range(il.begin(), il.end()); } #endif //! Requires: nh is empty or this->get_allocator() == nh.get_allocator(). @@ -1446,7 +1448,7 @@ class multimap typedef typename BOOST_CONTAINER_IMPDEF(base_t::const_iterator) const_iterator; typedef typename BOOST_CONTAINER_IMPDEF(base_t::reverse_iterator) reverse_iterator; typedef typename BOOST_CONTAINER_IMPDEF(base_t::const_reverse_iterator) const_reverse_iterator; - typedef std::pair nonconst_value_type; + //typedef std::pair nonconst_value_type; typedef BOOST_CONTAINER_IMPDEF(movable_value_type_impl) movable_value_type; typedef BOOST_CONTAINER_IMPDEF(node_handle< typename base_t::stored_allocator_type @@ -1836,28 +1838,28 @@ class multimap //! //! Complexity: Logarithmic. BOOST_CONTAINER_FORCEINLINE iterator insert(const value_type& x) - { return this->base_t::insert_equal(x); } + { return this->base_t::insert_equal_convertible(x); } + + //! Effects: Inserts a new value move-constructed from x and returns + //! the iterator pointing to the newly inserted element. + //! + //! Complexity: Logarithmic. + BOOST_CONTAINER_FORCEINLINE iterator insert(BOOST_RV_REF(value_type) x) + { return this->base_t::insert_equal_convertible(boost::move(x)); } //! Effects: Inserts a new value constructed from x and returns //! the iterator pointing to the newly inserted element. //! //! Complexity: Logarithmic. - BOOST_CONTAINER_FORCEINLINE iterator insert(const nonconst_value_type& x) - { return this->base_t::emplace_equal(x); } - - //! Effects: Inserts a new value move-constructed from x and returns - //! the iterator pointing to the newly inserted element. - //! - //! Complexity: Logarithmic. - BOOST_CONTAINER_FORCEINLINE iterator insert(BOOST_RV_REF(nonconst_value_type) x) - { return this->base_t::emplace_equal(boost::move(x)); } - - //! Effects: Inserts a new value move-constructed from x and returns - //! the iterator pointing to the newly inserted element. - //! - //! Complexity: Logarithmic. - iterator insert(BOOST_RV_REF(movable_value_type) x) - { return this->base_t::emplace_equal(boost::move(x)); } + template + BOOST_CONTAINER_FORCEINLINE BOOST_CONTAINER_DOC1ST + ( iterator + , typename dtl::enable_if_c< + dtl::is_convertible::value || + dtl::is_convertible::value + BOOST_MOVE_I iterator >::type) + insert(BOOST_FWD_REF(Pair) x) + { return this->base_t::emplace_equal(boost::forward(x)); } //! Effects: Inserts a copy of x in the container. //! p is a hint pointing to where the insert should start to search. @@ -1868,29 +1870,7 @@ class multimap //! Complexity: Logarithmic in general, but amortized constant if t //! is inserted right before p. BOOST_CONTAINER_FORCEINLINE iterator insert(const_iterator p, const value_type& x) - { return this->base_t::insert_equal(p, x); } - - //! Effects: Inserts a new value constructed from x in the container. - //! p is a hint pointing to where the insert should start to search. - //! - //! Returns: An iterator pointing to the element with key equivalent - //! to the key of x. - //! - //! Complexity: Logarithmic in general, but amortized constant if t - //! is inserted right before p. - BOOST_CONTAINER_FORCEINLINE iterator insert(const_iterator p, const nonconst_value_type& x) - { return this->base_t::emplace_hint_equal(p, x); } - - //! Effects: Inserts a new value move constructed from x in the container. - //! p is a hint pointing to where the insert should start to search. - //! - //! Returns: An iterator pointing to the element with key equivalent - //! to the key of x. - //! - //! Complexity: Logarithmic in general, but amortized constant if t - //! is inserted right before p. - BOOST_CONTAINER_FORCEINLINE iterator insert(const_iterator p, BOOST_RV_REF(nonconst_value_type) x) - { return this->base_t::emplace_hint_equal(p, boost::move(x)); } + { return this->base_t::insert_equal_hint_convertible(p, x); } //! Effects: Inserts a new value move constructed from x in the container. //! p is a hint pointing to where the insert should start to search. @@ -1901,7 +1881,25 @@ class multimap //! Complexity: Logarithmic in general, but amortized constant if t //! is inserted right before p. BOOST_CONTAINER_FORCEINLINE iterator insert(const_iterator p, BOOST_RV_REF(movable_value_type) x) - { return this->base_t::emplace_hint_equal(p, boost::move(x)); } + { return this->base_t::insert_equal_hint_convertible(p, boost::move(x)); } + + //! Effects: Inserts a new value constructed from x in the container. + //! p is a hint pointing to where the insert should start to search. + //! + //! Returns: An iterator pointing to the element with key equivalent + //! to the key of x. + //! + //! Complexity: Logarithmic in general, but amortized constant if t + //! is inserted right before p. + template + BOOST_CONTAINER_FORCEINLINE BOOST_CONTAINER_DOC1ST + ( iterator + , typename dtl::enable_if_c< + dtl::is_convertible::value || + dtl::is_convertible::value + BOOST_MOVE_I iterator>::type) + insert(const_iterator p, BOOST_FWD_REF(Pair) x) + { return this->base_t::emplace_hint_equal(p, boost::forward(x)); } //! Requires: first, last are not iterators into *this. //! @@ -1910,14 +1908,14 @@ class multimap //! Complexity: At most N log(size()+N) (N is the distance from first to last) template BOOST_CONTAINER_FORCEINLINE void insert(InputIterator first, InputIterator last) - { this->base_t::insert_equal(first, last); } + { this->base_t::insert_equal_range(first, last); } #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) //! Effects: inserts each element from the range [il.begin(), il.end(). //! //! Complexity: At most N log(size()+N) (N is the distance from il.begin() to il.end()) BOOST_CONTAINER_FORCEINLINE void insert(std::initializer_list il) - { this->base_t::insert_equal(il.begin(), il.end()); } + { this->base_t::insert_equal_range(il.begin(), il.end()); } #endif //! Requires: nh is empty or this->get_allocator() == nh.get_allocator(). diff --git a/include/boost/container/set.hpp b/include/boost/container/set.hpp index 14b5b6b..a9c3bc3 100644 --- a/include/boost/container/set.hpp +++ b/include/boost/container/set.hpp @@ -597,7 +597,8 @@ class set private: typedef std::pair insert_return_pair; public: - BOOST_MOVE_CONVERSION_AWARE_CATCH(insert, value_type, insert_return_pair, this->priv_insert) + BOOST_MOVE_CONVERSION_AWARE_CATCH + (insert, value_type, insert_return_pair, this->base_t::insert_unique_convertible) #endif #if defined(BOOST_CONTAINER_DOXYGEN_INVOKED) @@ -620,7 +621,8 @@ class set //! Complexity: Logarithmic. iterator insert(const_iterator p, value_type &&x); #else - BOOST_MOVE_CONVERSION_AWARE_CATCH_1ARG(insert, value_type, iterator, this->priv_insert, const_iterator, const_iterator) + BOOST_MOVE_CONVERSION_AWARE_CATCH_1ARG + (insert, value_type, iterator, this->base_t::insert_unique_hint_convertible, const_iterator, const_iterator) #endif //! Requires: first, last are not iterators into *this. @@ -631,7 +633,7 @@ class set //! Complexity: At most N log(size()+N) (N is the distance from first to last) template BOOST_CONTAINER_FORCEINLINE void insert(InputIterator first, InputIterator last) - { this->base_t::insert_unique(first, last); } + { this->base_t::insert_unique_range(first, last); } #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) //! Effects: inserts each element from the range [il.begin(),il.end()) if and only @@ -639,7 +641,7 @@ class set //! //! Complexity: At most N log(size()+N) (N is the distance from il.begin() to il.end()) BOOST_CONTAINER_FORCEINLINE void insert(std::initializer_list il) - { this->base_t::insert_unique(il.begin(), il.end()); } + { this->base_t::insert_unique_range(il.begin(), il.end()); } #endif //! @copydoc ::boost::container::map::insert(node_type&&) @@ -948,17 +950,6 @@ class set friend void swap(set& x, set& y); #endif //#if defined(BOOST_CONTAINER_DOXYGEN_INVOKED) - - #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED - private: - template - BOOST_CONTAINER_FORCEINLINE std::pair priv_insert(BOOST_FWD_REF(KeyType) x) - { return this->base_t::insert_unique(::boost::forward(x)); } - - template - BOOST_CONTAINER_FORCEINLINE iterator priv_insert(const_iterator p, BOOST_FWD_REF(KeyType) x) - { return this->base_t::insert_unique(p, ::boost::forward(x)); } - #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED }; #ifndef BOOST_CONTAINER_NO_CXX17_CTAD @@ -1393,7 +1384,7 @@ class multiset //! is inserted right before p. iterator insert(value_type &&x); #else - BOOST_MOVE_CONVERSION_AWARE_CATCH(insert, value_type, iterator, this->priv_insert) + BOOST_MOVE_CONVERSION_AWARE_CATCH(insert, value_type, iterator, this->base_t::insert_equal_convertible) #endif #if defined(BOOST_CONTAINER_DOXYGEN_INVOKED) @@ -1417,7 +1408,8 @@ class multiset //! is inserted right before p. iterator insert(const_iterator p, value_type &&x); #else - BOOST_MOVE_CONVERSION_AWARE_CATCH_1ARG(insert, value_type, iterator, this->priv_insert, const_iterator, const_iterator) + BOOST_MOVE_CONVERSION_AWARE_CATCH_1ARG + (insert, value_type, iterator, this->base_t::insert_equal_hint_convertible, const_iterator, const_iterator) #endif //! Requires: first, last are not iterators into *this. @@ -1427,12 +1419,12 @@ class multiset //! Complexity: At most N log(size()+N) (N is the distance from first to last) template BOOST_CONTAINER_FORCEINLINE void insert(InputIterator first, InputIterator last) - { this->base_t::insert_equal(first, last); } + { this->base_t::insert_equal_range(first, last); } #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) //! @copydoc ::boost::container::set::insert(std::initializer_list) BOOST_CONTAINER_FORCEINLINE void insert(std::initializer_list il) - { this->base_t::insert_equal(il.begin(), il.end()); } + { this->base_t::insert_equal_range(il.begin(), il.end()); } #endif //! @copydoc ::boost::container::multimap::insert(node_type&&) @@ -1611,18 +1603,6 @@ class multiset friend void swap(multiset& x, multiset& y); #endif //#if defined(BOOST_CONTAINER_DOXYGEN_INVOKED) - - #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED - private: - template - BOOST_CONTAINER_FORCEINLINE iterator priv_insert(BOOST_FWD_REF(KeyType) x) - { return this->base_t::insert_equal(::boost::forward(x)); } - - template - BOOST_CONTAINER_FORCEINLINE iterator priv_insert(const_iterator p, BOOST_FWD_REF(KeyType) x) - { return this->base_t::insert_equal(p, ::boost::forward(x)); } - - #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED }; #ifndef BOOST_CONTAINER_NO_CXX17_CTAD