diff --git a/include/boost/container/detail/flat_tree.hpp b/include/boost/container/detail/flat_tree.hpp index 0deb7eb..99d8ffa 100644 --- a/include/boost/container/detail/flat_tree.hpp +++ b/include/boost/container/detail/flat_tree.hpp @@ -885,6 +885,18 @@ class flat_tree return ret; } + template + std::pair insert_unique(BOOST_FWD_REF(Convertible) val) + { + std::pair ret; + insert_commit_data data; + ret.second = this->priv_insert_unique_prepare(KeyOfValue()(val), data); + ret.first = ret.second ? this->priv_insert_commit(data, boost::move(val)) + : this->begin() + (data.position - this->cbegin()); + //: iterator(vector_iterator_get_ptr(data.position)); + return ret; + } + iterator insert_equal(const value_type& val) { iterator i = this->upper_bound(KeyOfValue()(val)); @@ -919,6 +931,21 @@ class flat_tree //: iterator(vector_iterator_get_ptr(data.position)); } + template + inline typename dtl::enable_if_c< + !dtl::is_convertible::value && //not convertible to iterator + !dtl::is_convertible::value //not convertible to const_iterator + , iterator>::type + insert_unique(const_iterator hint, BOOST_FWD_REF(K) val) + { + BOOST_ASSERT(this->priv_in_range_or_end(hint)); + insert_commit_data data; + return this->priv_insert_unique_prepare(hint, KeyOfValue()(val), data) + ? this->priv_insert_commit(data, boost::move(val)) + : this->begin() + (data.position - this->cbegin()); + //: iterator(vector_iterator_get_ptr(data.position)); + } + iterator insert_equal(const_iterator hint, const value_type& val) { BOOST_ASSERT(this->priv_in_range_or_end(hint)); @@ -936,7 +963,7 @@ class flat_tree } template - void insert_unique(InIt first, InIt last) + void insert_unique_range(InIt first, InIt last) { dtl::bool_::value> contiguous_tag; container_type &seq = this->m_data.m_seq; @@ -963,7 +990,7 @@ class flat_tree } template - void insert_equal(InIt first, InIt last) + void insert_equal_range(InIt first, InIt last) { if (first != last) { dtl::bool_::value> contiguous_tag; @@ -977,7 +1004,7 @@ class flat_tree //Ordered template - void insert_equal(ordered_range_t, InIt first, InIt last) + void insert_equal_range(ordered_range_t, InIt first, InIt last) { const bool value = boost::container::dtl:: has_member_function_callable_with_merge_unique::value; @@ -985,7 +1012,7 @@ class flat_tree } template - void insert_unique(ordered_unique_range_t, InIt first, InIt last) + void insert_unique_range(ordered_unique_range_t, InIt first, InIt last) { const bool value = boost::container::dtl:: has_member_function_callable_with_merge_unique::value; @@ -1331,15 +1358,15 @@ class flat_tree template inline void merge_unique(flat_tree& source) { - this->insert_unique( boost::make_move_iterator(source.begin()) - , boost::make_move_iterator(source.end())); + this->insert_unique_range( boost::make_move_iterator(source.begin()) + , boost::make_move_iterator(source.end())); } template inline void merge_equal(flat_tree& source) { - this->insert_equal( boost::make_move_iterator(source.begin()) - , boost::make_move_iterator(source.end())); + this->insert_equal_range( boost::make_move_iterator(source.begin()) + , boost::make_move_iterator(source.end())); } inline void merge_unique(flat_tree& source) @@ -1541,10 +1568,10 @@ class flat_tree //for the constructor //Call end() every iteration as reallocation might have invalidated iterators if(unique_insertion){ - this->insert_unique(first, last); + this->insert_unique_range(first, last); } else{ - this->insert_equal (first, last); + this->insert_equal_range(first, last); } } @@ -1645,7 +1672,7 @@ class flat_tree inline iterator priv_insert_commit (insert_commit_data &commit_data, BOOST_FWD_REF(Convertible) convertible) { - return this->m_data.m_seq.insert + return this->m_data.m_seq.emplace ( commit_data.position , boost::forward(convertible)); } diff --git a/include/boost/container/detail/tree.hpp b/include/boost/container/detail/tree.hpp index 569d04a..feddb2f 100644 --- a/include/boost/container/detail/tree.hpp +++ b/include/boost/container/detail/tree.hpp @@ -813,25 +813,27 @@ class tree && boost::container::dtl::is_nothrow_swappable::value ) { AllocHolder::swap(x); } - public: + protected: typedef typename Icont::insert_commit_data insert_commit_data; // insert/erase + template std::pair insert_unique_check - (const key_type& key, insert_commit_data &data) + (const Comparable& key, insert_commit_data &data) { std::pair ret = - this->icont().insert_unique_check(key, data); + this->icont().insert_unique_check(key, KeyNodeCompare(key_comp()), data); return std::pair(iterator(ret.first), ret.second); } + template std::pair insert_unique_check - (const_iterator hint, const key_type& key, insert_commit_data &data) + (const_iterator hint, const Comparable& key, insert_commit_data &data) { BOOST_ASSERT((priv_is_linked)(hint)); std::pair ret = - this->icont().insert_unique_check(hint.get(), key, data); + this->icont().insert_unique_check(hint.get(), key, KeyNodeCompare(key_comp()), data); return std::pair(iterator(ret.first), ret.second); } @@ -850,8 +852,9 @@ class tree std::pair insert_unique_convertible(BOOST_FWD_REF(MovableConvertible) v) { insert_commit_data data; + const typename remove_cvref::type & k = v; //Support emulated rvalue references std::pair ret = - this->insert_unique_check(key_of_value_t()(v), data); + this->insert_unique_check(key_of_value_t()(k), data); if(ret.second){ ret.first = this->insert_unique_commit(boost::forward(v), data); } diff --git a/include/boost/container/flat_map.hpp b/include/boost/container/flat_map.hpp index 0fff739..e0d592a 100644 --- a/include/boost/container/flat_map.hpp +++ b/include/boost/container/flat_map.hpp @@ -1396,7 +1396,7 @@ class flat_map //! Note: If an element is inserted it might invalidate elements. template inline void insert(InputIterator first, InputIterator last) - { m_flat_tree.insert_unique(first, last); } + { m_flat_tree.insert_unique_range(first, last); } //! Requires: first, last are not iterators into *this. //! @@ -1414,7 +1414,7 @@ class flat_map //! Note: Non-standard extension. template inline void insert(ordered_unique_range_t, InputIterator first, InputIterator last) - { m_flat_tree.insert_unique(ordered_unique_range, first, last); } + { m_flat_tree.insert_unique_range(ordered_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 @@ -1425,8 +1425,8 @@ class flat_map //! Note: If an element is inserted it might invalidate elements. inline void insert(std::initializer_list il) { - m_flat_tree.insert_unique( dtl::force(il).begin() - , dtl::force(il).end()); + m_flat_tree.insert_unique_range( dtl::force(il).begin() + , dtl::force(il).end()); } //! Requires: [il.begin(), il.end()) must be ordered according to the predicate and must be @@ -1443,9 +1443,9 @@ class flat_map //! Note: Non-standard extension. inline void insert(ordered_unique_range_t, std::initializer_list il) { - m_flat_tree.insert_unique(ordered_unique_range - , dtl::force(il).begin() - , dtl::force(il).end()); + m_flat_tree.insert_unique_range(ordered_unique_range + , dtl::force(il).begin() + , dtl::force(il).end()); } #endif @@ -2794,7 +2794,7 @@ class flat_multimap //! Note: If an element is inserted it might invalidate elements. template inline void insert(InputIterator first, InputIterator last) - { m_flat_tree.insert_equal(first, last); } + { m_flat_tree.insert_equal_range(first, last); } //! Requires: first, last are not iterators into *this. //! @@ -2811,7 +2811,7 @@ class flat_multimap //! Note: Non-standard extension. template inline void insert(ordered_range_t, InputIterator first, InputIterator last) - { m_flat_tree.insert_equal(ordered_range, first, last); } + { m_flat_tree.insert_equal_range(ordered_range, first, last); } #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) //! Effects: inserts each element from the range [il.begin(), il.end()) . @@ -2821,8 +2821,8 @@ class flat_multimap //! Note: If an element is inserted it might invalidate elements. inline void insert(std::initializer_list il) { - m_flat_tree.insert_equal( dtl::force(il).begin() - , dtl::force(il).end()); + m_flat_tree.insert_equal_range( dtl::force(il).begin() + , dtl::force(il).end()); } //! Requires: [il.begin(), il.end()) must be ordered according to the predicate. @@ -2838,9 +2838,9 @@ class flat_multimap //! Note: Non-standard extension. inline void insert(ordered_range_t, std::initializer_list il) { - m_flat_tree.insert_equal( ordered_range - , dtl::force(il).begin() - , dtl::force(il).end()); + m_flat_tree.insert_equal_range( ordered_range + , dtl::force(il).begin() + , dtl::force(il).end()); } #endif diff --git a/include/boost/container/flat_set.hpp b/include/boost/container/flat_set.hpp index 672f3a2..15d1018 100644 --- a/include/boost/container/flat_set.hpp +++ b/include/boost/container/flat_set.hpp @@ -638,7 +638,7 @@ class flat_set #endif // !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) - #if defined(BOOST_CONTAINER_DOXYGEN_INVOKED) + #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED) //! Effects: Inserts x if and only if there is no element in the container //! with key equivalent to the key of x. //! @@ -650,7 +650,8 @@ class flat_set //! to the elements with bigger keys than x. //! //! Note: If an element is inserted it might invalidate elements. - std::pair insert(const value_type &x); + std::pair insert(const value_type &x) + { return this->tree_t::insert_unique(x); } //! 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. @@ -663,15 +664,35 @@ class flat_set //! to the elements with bigger keys than x. //! //! Note: If an element is inserted it might invalidate elements. - std::pair insert(value_type &&x); - #else - private: - typedef std::pair insert_return_pair; - public: - BOOST_MOVE_CONVERSION_AWARE_CATCH(insert, value_type, insert_return_pair, this->tree_t::insert_unique) - #endif + std::pair insert(value_type &&x) + { return this->tree_t::insert_unique(boost::move(x)); } + + //! Requires: This overload is available only if + //! key_compare::is_transparent exists. + //! + //! 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 search time plus linear insertion + //! to the elements with bigger keys than x. + //! + //! Note: If an element is inserted it might invalidate elements. + template + inline BOOST_CONTAINER_DOC1ST + (std::pair + , typename dtl::enable_if_c< + dtl::is_transparent::value && //transparent + !dtl::is_convertible::value && //not convertible to iterator + !dtl::is_convertible::value //not convertible to const_iterator + BOOST_MOVE_I std::pair + >::type) + insert(K &&x) + { return this->tree_t::insert_unique(boost::forward(x)); } - #if defined(BOOST_CONTAINER_DOXYGEN_INVOKED) //! 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. @@ -683,9 +704,11 @@ class flat_set //! right before p) plus insertion linear to the elements with bigger keys than x. //! //! Note: If an element is inserted it might invalidate elements. - iterator insert(const_iterator p, const value_type &x); + iterator insert(const_iterator p, const value_type &x) + { return this->tree_t::insert_unique(p, x); } - //! Effects: Inserts an element move constructed from x in the container. + //! Effects: Move-inserts 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. @@ -694,8 +717,38 @@ class flat_set //! right before p) plus insertion linear to the elements with bigger keys than x. //! //! Note: If an element is inserted it might invalidate elements. - iterator insert(const_iterator p, value_type &&x); + iterator insert(const_iterator p, value_type &&x) + { return this->tree_t::insert_unique(p, boost::move(x)); } + + //! Requires: This overload is available only if + //! key_compare::is_transparent exists. + //! + //! Effects: Forward-inserts 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 search time (constant if x is inserted + //! right before p) plus insertion linear to the elements with bigger keys than x. + //! + //! Note: If an element is inserted it might invalidate elements. + template + inline BOOST_CONTAINER_DOC1ST + ( iterator + , typename dtl::enable_if_transparent< key_compare + BOOST_MOVE_I K + BOOST_MOVE_I iterator + >::type) //transparent + insert(const_iterator p, K &&x) + { return this->tree_t::insert_unique(p, boost::forward(x)); } + #else + private: + typedef std::pair insert_return_pair; + public: + BOOST_MOVE_CONVERSION_AWARE_CATCH(insert, value_type, insert_return_pair, this->tree_t::insert_unique) BOOST_MOVE_CONVERSION_AWARE_CATCH_1ARG(insert, value_type, iterator, this->tree_t::insert_unique, const_iterator, const_iterator) #endif @@ -709,7 +762,7 @@ class flat_set //! Note: If an element is inserted it might invalidate elements. template inline void insert(InputIterator first, InputIterator last) - { this->tree_t::insert_unique(first, last); } + { this->tree_t::insert_unique_range(first, last); } //! Requires: first, last are not iterators into *this and //! must be ordered according to the predicate and must be @@ -723,7 +776,7 @@ class flat_set //! Note: Non-standard extension. If an element is inserted it might invalidate elements. template inline void insert(ordered_unique_range_t, InputIterator first, InputIterator last) - { this->tree_t::insert_unique(ordered_unique_range, first, last); } + { this->tree_t::insert_unique_range(ordered_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 @@ -733,7 +786,7 @@ class flat_set //! //! Note: If an element is inserted it might invalidate elements. inline void insert(std::initializer_list il) - { this->tree_t::insert_unique(il.begin(), il.end()); } + { this->tree_t::insert_unique_range(il.begin(), il.end()); } //! Requires: Range [il.begin(), il.end()) must be ordered according to the predicate //! and must be unique values. @@ -745,7 +798,7 @@ class flat_set //! //! Note: Non-standard extension. If an element is inserted it might invalidate elements. inline void insert(ordered_unique_range_t, std::initializer_list il) - { this->tree_t::insert_unique(ordered_unique_range, il.begin(), il.end()); } + { this->tree_t::insert_unique_range(ordered_unique_range, il.begin(), il.end()); } #endif //! @copydoc ::boost::container::flat_map::merge(flat_map&) @@ -1678,7 +1731,7 @@ class flat_multiset //! Note: If an element is inserted it might invalidate elements. template inline void insert(InputIterator first, InputIterator last) - { this->tree_t::insert_equal(first, last); } + { this->tree_t::insert_equal_range(first, last); } //! Requires: first, last are not iterators into *this and //! must be ordered according to the predicate. @@ -1691,7 +1744,7 @@ class flat_multiset //! Note: Non-standard extension. If an element is inserted it might invalidate elements. template inline void insert(ordered_range_t, InputIterator first, InputIterator last) - { this->tree_t::insert_equal(ordered_range, first, last); } + { this->tree_t::insert_equal_range(ordered_range, first, last); } #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) //! Effects: inserts each element from the range [il.begin(), il.end()). @@ -1700,7 +1753,7 @@ class flat_multiset //! //! Note: If an element is inserted it might invalidate elements. inline void insert(std::initializer_list il) - { this->tree_t::insert_equal(il.begin(), il.end()); } + { this->tree_t::insert_equal_range(il.begin(), il.end()); } //! Requires: Range [il.begin(), il.end()) must be ordered according to the predicate. //! @@ -1711,7 +1764,7 @@ class flat_multiset //! //! Note: Non-standard extension. If an element is inserted it might invalidate elements. inline void insert(ordered_range_t, std::initializer_list il) - { this->tree_t::insert_equal(ordered_range, il.begin(), il.end()); } + { this->tree_t::insert_equal_range(ordered_range, il.begin(), il.end()); } #endif //! @copydoc ::boost::container::flat_multimap::merge(flat_multimap&) diff --git a/include/boost/container/set.hpp b/include/boost/container/set.hpp index 722bef1..2c32cad 100644 --- a/include/boost/container/set.hpp +++ b/include/boost/container/set.hpp @@ -574,7 +574,7 @@ class set #endif // !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) - #if defined(BOOST_CONTAINER_DOXYGEN_INVOKED) + #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED) //! Effects: Inserts x if and only if there is no element in the container //! with key equivalent to the key of x. //! @@ -583,7 +583,8 @@ class set //! points to the element with key equivalent to the key of x. //! //! Complexity: Logarithmic. - std::pair insert(const value_type &x); + std::pair insert(const value_type &x) + { 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. @@ -593,16 +594,32 @@ class set //! points to the element with key equivalent to the key of x. //! //! Complexity: Logarithmic. - std::pair insert(value_type &&x); - #else - private: - typedef std::pair insert_return_pair; - public: - BOOST_MOVE_CONVERSION_AWARE_CATCH - (insert, value_type, insert_return_pair, this->base_t::insert_unique_convertible) - #endif + std::pair insert(value_type &&x) + { return this->base_t::insert_unique_convertible(boost::move(x)); } + + //! Requires: This overload is available only if + //! key_compare::is_transparent exists. + //! + //! Effects: Forward 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. + //! + //! 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 + inline BOOST_CONTAINER_DOC1ST + (std::pair + , typename dtl::enable_if_c< + dtl::is_transparent::value && //transparent + !dtl::is_convertible::value && //not convertible to iterator + !dtl::is_convertible::value //not convertible to const_iterator + BOOST_MOVE_I std::pair + >::type) + insert(K &&x) + { return this->base_t::insert_unique_convertible(boost::forward(x)); } - #if defined(BOOST_CONTAINER_DOXYGEN_INVOKED) //! 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. @@ -612,7 +629,8 @@ class set //! //! Complexity: Logarithmic in general, but amortized constant if t //! is inserted right before p. - iterator insert(const_iterator p, const value_type &x); + iterator insert(const_iterator p, const value_type &x) + { return this->base_t::insert_unique_hint_convertible(p, x); } //! Effects: Inserts an element move constructed from x in the container. //! p is a hint pointing to where the insert should start to search. @@ -620,8 +638,38 @@ class set //! Returns: An iterator pointing to the element with key equivalent to the key of x. //! //! Complexity: Logarithmic. - iterator insert(const_iterator p, value_type &&x); + iterator insert(const_iterator p, value_type &&x) + { return this->base_t::insert_unique_hint_convertible(p, boost::move(x)); } + + //! Requires: This overload is available only if + //! key_compare::is_transparent exists. + //! + //! Requires: This overload is available only if + //! key_compare::is_transparent exists. + //! + //! Effects: Inserts an element forward 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. + template + inline BOOST_CONTAINER_DOC1ST + ( iterator + , typename dtl::enable_if_transparent< key_compare + BOOST_MOVE_I K + BOOST_MOVE_I iterator + >::type) //transparent + insert(const_iterator p, K &&x) + { return this->base_t::insert_unique_hint_convertible(p, boost::forward(x)); } + #else + private: + typedef std::pair insert_return_pair; + public: + BOOST_MOVE_CONVERSION_AWARE_CATCH + (insert, value_type, insert_return_pair, this->base_t::insert_unique_convertible) + BOOST_MOVE_CONVERSION_AWARE_CATCH_1ARG (insert, value_type, iterator, this->base_t::insert_unique_hint_convertible, const_iterator, const_iterator) #endif diff --git a/test/flat_set_test.cpp b/test/flat_set_test.cpp index 2aea2cb..ff62d20 100644 --- a/test/flat_set_test.cpp +++ b/test/flat_set_test.cpp @@ -495,104 +495,6 @@ bool flat_tree_extract_adopt_test() return true; } -bool test_heterogeneous_lookups() -{ - typedef flat_set set_t; - typedef flat_multiset mset_t; - - set_t set1; - mset_t mset1; - - const set_t &cset1 = set1; - const mset_t &cmset1 = mset1; - - set1.insert(1); - set1.insert(1); - set1.insert(2); - set1.insert(2); - set1.insert(3); - - mset1.insert(1); - mset1.insert(1); - mset1.insert(2); - mset1.insert(2); - mset1.insert(3); - - const test::non_copymovable_int find_me(2); - - //find - if(*set1.find(find_me) != 2) - return false; - if(*cset1.find(find_me) != 2) - return false; - if(*mset1.find(find_me) != 2) - return false; - if(*cmset1.find(find_me) != 2) - return false; - - //count - if(set1.count(find_me) != 1) - return false; - if(cset1.count(find_me) != 1) - return false; - if(mset1.count(find_me) != 2) - return false; - if(cmset1.count(find_me) != 2) - return false; - - //contains - if(!set1.contains(find_me)) - return false; - if(!cset1.contains(find_me)) - return false; - if(!mset1.contains(find_me)) - return false; - if(!cmset1.contains(find_me)) - return false; - - //lower_bound - if(*set1.lower_bound(find_me) != 2) - return false; - if(*cset1.lower_bound(find_me) != 2) - return false; - if(*mset1.lower_bound(find_me) != 2) - return false; - if(*cmset1.lower_bound(find_me) != 2) - return false; - - //upper_bound - if(*set1.upper_bound(find_me) != 3) - return false; - if(*cset1.upper_bound(find_me) != 3) - return false; - if(*mset1.upper_bound(find_me) != 3) - return false; - if(*cmset1.upper_bound(find_me) != 3) - return false; - - //equal_range - if(*set1.equal_range(find_me).first != 2) - return false; - if(*cset1.equal_range(find_me).second != 3) - return false; - if(*mset1.equal_range(find_me).first != 2) - return false; - if(*cmset1.equal_range(find_me).second != 3) - return false; - - //erase - if (set1.erase(find_me) != 1) - return false; - if (set1.erase(find_me) != 0) - return false; - if (mset1.erase(find_me) != 2) - return false; - if (mset1.erase(find_me) != 0) - return false; - - return true; -} - // An ordered sequence of std:pair is also ordered by std::pair::first. struct with_lookup_by_first { @@ -765,9 +667,16 @@ int main() if (!boost::container::test::instantiate_constructors, flat_multiset >()) return 1; - if(!test_heterogeneous_lookups()){ + if (!test::test_heterogeneous_lookup + < flat_set + , flat_multiset + >()) + return 1; + + if (!test::test_heterogeneous_insert + < flat_set + >()) return 1; - } if(!test_heterogeneous_lookup_by_partial_key()){ return 1; diff --git a/test/set_test.cpp b/test/set_test.cpp index 79a8483..30ca493 100644 --- a/test/set_test.cpp +++ b/test/set_test.cpp @@ -189,6 +189,33 @@ bool node_type_test() if(dst.size() != 5) return false; } + { + typedef set set_t; + typedef multiset mset_t; + + set_t set1; + mset_t mset1; + //extract + const test::non_copymovable_int extract_me(1); + + set1.insert(1); + mset1.emplace(1); + mset1.emplace(1); + + //extract + if (!set1.extract(1)) + return false; + if (set1.extract(1)) + return false; + + if (!mset1.extract(1)) + return false; + if (!mset1.extract(1)) + return false; + if (mset1.extract(1)) + return false; + + } return true; } @@ -352,127 +379,9 @@ void test_merge_from_different_comparison() set1.merge(set2); } -bool test_heterogeneous_lookups() -{ - typedef set set_t; - typedef multiset mset_t; - - set_t set1; - mset_t mset1; - - const set_t &cset1 = set1; - const mset_t &cmset1 = mset1; - - set1.insert(1); - set1.insert(1); - set1.insert(2); - set1.insert(2); - set1.insert(3); - - mset1.insert(1); - mset1.insert(1); - mset1.insert(2); - mset1.insert(2); - mset1.insert(3); - - const test::non_copymovable_int find_me(2); - - //find - if(*set1.find(find_me) != 2) - return false; - if(*cset1.find(find_me) != 2) - return false; - if(*mset1.find(find_me) != 2) - return false; - if(*cmset1.find(find_me) != 2) - return false; - - //count - if(set1.count(find_me) != 1) - return false; - if(cset1.count(find_me) != 1) - return false; - if(mset1.count(find_me) != 2) - return false; - if(cmset1.count(find_me) != 2) - return false; - - //contains - if(!set1.contains(find_me)) - return false; - if(!cset1.contains(find_me)) - return false; - if(!mset1.contains(find_me)) - return false; - if(!cmset1.contains(find_me)) - return false; - - //lower_bound - if(*set1.lower_bound(find_me) != 2) - return false; - if(*cset1.lower_bound(find_me) != 2) - return false; - if(*mset1.lower_bound(find_me) != 2) - return false; - if(*cmset1.lower_bound(find_me) != 2) - return false; - - //upper_bound - if(*set1.upper_bound(find_me) != 3) - return false; - if(*cset1.upper_bound(find_me) != 3) - return false; - if(*mset1.upper_bound(find_me) != 3) - return false; - if(*cmset1.upper_bound(find_me) != 3) - return false; - - //equal_range - if(*set1.equal_range(find_me).first != 2) - return false; - if(*cset1.equal_range(find_me).second != 3) - return false; - if(*mset1.equal_range(find_me).first != 2) - return false; - if(*cmset1.equal_range(find_me).second != 3) - return false; - - //erase - if (set1.erase(find_me) != 1) - return false; - if (set1.erase(find_me) != 0) - return false; - if (mset1.erase(find_me) != 2) - return false; - if (mset1.erase(find_me) != 0) - return false; - - //extract - set1.clear(); - set1.insert(1); - mset1.clear(); - mset1.insert(1); - mset1.insert(1); - - const test::non_copymovable_int extract_me(1); - - if (!set1.extract(extract_me)) - return false; - if (set1.extract(extract_me)) - return false; - - if (!mset1.extract(extract_me)) - return false; - if (!mset1.extract(extract_me)) - return false; - if (mset1.extract(extract_me)) - return false; - - return true; -} - int main () { + using namespace boost::container::test; //Recursive container instantiation { set set_; @@ -509,7 +418,15 @@ int main () return 1; } - if(!test_heterogeneous_lookups()) + if (!test::test_heterogeneous_lookup + < set + , multiset + >()) + return 1; + + if (!test::test_heterogeneous_insert + < set + >()) return 1; //////////////////////////////////// diff --git a/test/set_test.hpp b/test/set_test.hpp index b564424..49a1fb1 100644 --- a/test/set_test.hpp +++ b/test/set_test.hpp @@ -1002,6 +1002,146 @@ bool instantiate_constructors() return true; } + + + + + + +template +bool test_heterogeneous_lookup() +{ + typedef IntSetType set_t; + typedef IntMultisetType mset_t; + + set_t set1; + mset_t mset1; + + const set_t &cset1 = set1; + const mset_t &cmset1 = mset1; + + set1.insert(1); + set1.insert(1); + set1.insert(2); + set1.insert(2); + set1.insert(3); + + mset1.insert(1); + mset1.insert(1); + mset1.insert(2); + mset1.insert(2); + mset1.insert(3); + + const test::non_copymovable_int find_me(2); + + //find + if(*set1.find(find_me) != 2) + return false; + if(*cset1.find(find_me) != 2) + return false; + if(*mset1.find(find_me) != 2) + return false; + if(*cmset1.find(find_me) != 2) + return false; + + //count + if(set1.count(find_me) != 1) + return false; + if(cset1.count(find_me) != 1) + return false; + if(mset1.count(find_me) != 2) + return false; + if(cmset1.count(find_me) != 2) + return false; + + //contains + if(!set1.contains(find_me)) + return false; + if(!cset1.contains(find_me)) + return false; + if(!mset1.contains(find_me)) + return false; + if(!cmset1.contains(find_me)) + return false; + + //lower_bound + if(*set1.lower_bound(find_me) != 2) + return false; + if(*cset1.lower_bound(find_me) != 2) + return false; + if(*mset1.lower_bound(find_me) != 2) + return false; + if(*cmset1.lower_bound(find_me) != 2) + return false; + + //upper_bound + if(*set1.upper_bound(find_me) != 3) + return false; + if(*cset1.upper_bound(find_me) != 3) + return false; + if(*mset1.upper_bound(find_me) != 3) + return false; + if(*cmset1.upper_bound(find_me) != 3) + return false; + + //equal_range + if(*set1.equal_range(find_me).first != 2) + return false; + if(*cset1.equal_range(find_me).second != 3) + return false; + if(*mset1.equal_range(find_me).first != 2) + return false; + if(*cmset1.equal_range(find_me).second != 3) + return false; + + //erase + if (set1.erase(find_me) != 1) + return false; + if (set1.erase(find_me) != 0) + return false; + if (mset1.erase(find_me) != 2) + return false; + if (mset1.erase(find_me) != 0) + return false; + + return true; +} + +template +bool test_heterogeneous_insert() +{ + typedef MovableIntSetType set_t; + + set_t set1; + const set_t &cset1 = set1; + + //insert + if(!set1.insert(1).second) + return false; + if (cset1.find(1) == cset1.end()) + return false; + if(set1.insert(1).second) + return false; + if (cset1.find(1) == cset1.end()) + return false; + + //insert with hint + if(set1.find(2) != set1.end()) + return false; + typename set_t::iterator i = set1.insert(set1.begin(), 2); + if(i != set1.insert(set1.end(), 2)) + return false; + if (cset1.find(2) == cset1.end()) + return false; + return true; +} + + + + + + + } //namespace test{ } //namespace container { } //namespace boost{