diff --git a/doc/intrusive.qbk b/doc/intrusive.qbk index cf1567d..e3c1106 100644 --- a/doc/intrusive.qbk +++ b/doc/intrusive.qbk @@ -3835,6 +3835,12 @@ to be inserted in intrusive containers are allocated using `std::vector` or `std [section:release_notes Release Notes] +[section:release_notes_boost_1_63_00 Boost 1.63 Release] + +* Implemented `merge` functions in ordered associative containers. + +[endsect] + [section:release_notes_boost_1_62_00 Boost 1.62 Release] * Fixed bugs: diff --git a/include/boost/intrusive/avl_set.hpp b/include/boost/intrusive/avl_set.hpp index 2c96204..b7e198c 100644 --- a/include/boost/intrusive/avl_set.hpp +++ b/include/boost/intrusive/avl_set.hpp @@ -26,6 +26,11 @@ namespace boost { namespace intrusive { +#if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) +template +class avl_multiset_impl; +#endif + //! The class template avl_set is an intrusive container, that mimics most of //! the interface of std::set as described in the C++ standard. //! @@ -399,6 +404,26 @@ class avl_set_impl //! @copydoc ::boost::intrusive::avltree::remove_node void remove_node(reference value); + + //! @copydoc ::boost::intrusive::avltree::merge_unique + template + void merge(avl_set &source); + + //! @copydoc ::boost::intrusive::avltree::merge_unique + template + void merge(avl_multiset &source); + + #else + + template + void merge(avl_set_impl &source) + { return tree_type::merge_unique(source); } + + + template + void merge(avl_multiset_impl &source) + { return tree_type::merge_unique(source); } + #endif //#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED }; @@ -865,6 +890,25 @@ class avl_multiset_impl //! @copydoc ::boost::intrusive::avltree::remove_node void remove_node(reference value); + + //! @copydoc ::boost::intrusive::avltree::merge_equal + template + void merge(avl_multiset &source); + + //! @copydoc ::boost::intrusive::avltree::merge_equal + template + void merge(avl_set &source); + + #else + + template + void merge(avl_multiset_impl &source) + { return tree_type::merge_equal(source); } + + template + void merge(avl_set_impl &source) + { return tree_type::merge_equal(source); } + #endif //#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED }; diff --git a/include/boost/intrusive/avltree.hpp b/include/boost/intrusive/avltree.hpp index 741d482..6a4e098 100644 --- a/include/boost/intrusive/avltree.hpp +++ b/include/boost/intrusive/avltree.hpp @@ -427,6 +427,14 @@ class avltree_impl //! @copydoc ::boost::intrusive::bstree::remove_node void remove_node(reference value); + //! @copydoc ::boost::intrusive::bstree::merge_unique(bstree&) + template + void merge_unique(avltree &); + + //! @copydoc ::boost::intrusive::bstree::merge_equal(bstree&) + template + void merge_equal(avltree &); + friend bool operator< (const avltree_impl &x, const avltree_impl &y); friend bool operator==(const avltree_impl &x, const avltree_impl &y); diff --git a/include/boost/intrusive/avltree_algorithms.hpp b/include/boost/intrusive/avltree_algorithms.hpp index 60a981c..1459851 100644 --- a/include/boost/intrusive/avltree_algorithms.hpp +++ b/include/boost/intrusive/avltree_algorithms.hpp @@ -269,14 +269,35 @@ class avltree_algorithms { typename bstree_algo::data_for_rebalance info; bstree_algo::erase(header, z, info); - if(info.y != z){ - NodeTraits::set_balance(info.y, NodeTraits::get_balance(z)); - } - //Rebalance avltree - rebalance_after_erasure(header, info.x, info.x_parent); + rebalance_after_erasure(header, z, info); return z; } + //! @copydoc ::boost::intrusive::bstree_algorithms::transfer_unique + template + static bool transfer_unique + (const node_ptr & header1, NodePtrCompare comp, const node_ptr &header2, const node_ptr & z) + { + typename bstree_algo::data_for_rebalance info; + bool const transferred = bstree_algo::transfer_unique(header1, comp, header2, z, info); + if(transferred){ + rebalance_after_erasure(header2, z, info); + rebalance_after_insertion(header1, z); + } + return transferred; + } + + //! @copydoc ::boost::intrusive::bstree_algorithms::transfer_equal + template + static void transfer_equal + (const node_ptr & header1, NodePtrCompare comp, const node_ptr &header2, const node_ptr & z) + { + typename bstree_algo::data_for_rebalance info; + bstree_algo::transfer_equal(header1, comp, header2, z, info); + rebalance_after_erasure(header2, z, info); + rebalance_after_insertion(header1, z); + } + //! @copydoc ::boost::intrusive::bstree_algorithms::clone(const const_node_ptr&,const node_ptr&,Cloner,Disposer) template static void clone @@ -461,7 +482,17 @@ class avltree_algorithms return true; } - static void rebalance_after_erasure(const node_ptr & header, node_ptr x, node_ptr x_parent) + static void rebalance_after_erasure + ( const node_ptr & header, const node_ptr &z, const typename bstree_algo::data_for_rebalance &info) + { + if(info.y != z){ + NodeTraits::set_balance(info.y, NodeTraits::get_balance(z)); + } + //Rebalance avltree + rebalance_after_erasure_restore_invariants(header, info.x, info.x_parent); + } + + static void rebalance_after_erasure_restore_invariants(const node_ptr & header, node_ptr x, node_ptr x_parent) { for ( node_ptr root = NodeTraits::get_parent(header) ; x != root diff --git a/include/boost/intrusive/bs_set.hpp b/include/boost/intrusive/bs_set.hpp index 60f18a1..75d334c 100644 --- a/include/boost/intrusive/bs_set.hpp +++ b/include/boost/intrusive/bs_set.hpp @@ -23,6 +23,11 @@ # pragma once #endif +#if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) +template +class bs_multiset_impl; +#endif + namespace boost { namespace intrusive { @@ -396,6 +401,26 @@ class bs_set_impl //! @copydoc ::boost::intrusive::bstree::remove_node void remove_node(reference value); + + //! @copydoc ::boost::intrusive::bstree::merge_unique + template + void merge(bs_set &source); + + //! @copydoc ::boost::intrusive::bstree::merge_unique + template + void merge(bs_multiset &source); + + #else + + template + void merge(bs_set_impl &source) + { return tree_type::merge_unique(source); } + + + template + void merge(bs_multiset_impl &source) + { return tree_type::merge_unique(source); } + #endif //#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED }; @@ -861,6 +886,25 @@ class bs_multiset_impl //! @copydoc ::boost::intrusive::bstree::remove_node void remove_node(reference value); + + //! @copydoc ::boost::intrusive::bstree::merge_equal + template + void merge(bs_multiset &source); + + //! @copydoc ::boost::intrusive::bstree::merge_equal + template + void merge(bs_set &source); + + #else + + template + void merge(bs_multiset_impl &source) + { return tree_type::merge_equal(source); } + + template + void merge(bs_set_impl &source) + { return tree_type::merge_equal(source); } + #endif //#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED }; diff --git a/include/boost/intrusive/bstree.hpp b/include/boost/intrusive/bstree.hpp index 4b7bbe5..e2007e1 100644 --- a/include/boost/intrusive/bstree.hpp +++ b/include/boost/intrusive/bstree.hpp @@ -364,7 +364,7 @@ struct bstbase2 { typedef detail::key_nodeptr_comp type; }; template - typename key_node_comp_ret::type key_node_comp(KeyTypeKeyCompare comp) const + BOOST_INTRUSIVE_FORCEINLINE typename key_node_comp_ret::type key_node_comp(KeyTypeKeyCompare comp) const { return detail::key_nodeptr_comp(comp, &this->get_value_traits()); } @@ -1163,6 +1163,36 @@ class bstree_impl #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED + //! Effects: Checks if a value can be inserted in the container, using + //! a user provided key instead of the value itself. + //! + //! Returns: If there is an equivalent value + //! returns a pair containing an iterator to the already present value + //! and false. If the value can be inserted returns true in the returned + //! pair boolean and fills "commit_data" that is meant to be used with + //! the "insert_commit" function. + //! + //! Complexity: Average complexity is at most logarithmic. + //! + //! Throws: If the comp ordering function throws. Strong guarantee. + std::pair insert_unique_check(const key_type &key, insert_commit_data &commit_data); + + //! Effects: Checks if a value can be inserted in the container, using + //! a user provided key instead of the value itself, using "hint" + //! as a hint to where it will be inserted. + //! + //! Returns: If there is an equivalent value + //! returns a pair containing an iterator to the already present value + //! and false. If the value can be inserted returns true in the returned + //! pair boolean and fills "commit_data" that is meant to be used with + //! the "insert_commit" function. + //! + //! Complexity: Logarithmic in general, but it's amortized + //! constant time if t is inserted immediately before hint. + //! + //! Throws: If the comp ordering function throws. Strong guarantee. + std::pair insert_unique_check(const_iterator hint, const key_type &key, insert_commit_data &commit_data); + //! Requires: comp must be a comparison function that induces //! the same strict weak ordering as key_compare. The difference is that //! comp compares an arbitrary key with the contained values. @@ -1914,6 +1944,78 @@ class bstree_impl node_algorithms::init(to_remove); } + //! Requires: "source" container's Options can only can differ in the comparison + //! function from *this. + //! + //! Effects: Attempts to extract each element in source and insert it into a using + //! the comparison object of *this. If there is an element in a with key equivalent to the + //! key of an element from source, then that element is not extracted from source. + //! + //! Postcondition: Pointers and references to the transferred elements of source refer + //! to those same elements but as members of *this. Iterators referring to the transferred + //! elements will continue to refer to their elements, but they now behave as iterators into *this, + //! not into source. + //! + //! Throws: Nothing unless the comparison object throws. + //! + //! Complexity: N log(a.size() + N) (N has the value source.size()) + #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) + template void merge_unique(bstree &); + #else + template + void merge_unique(bstree_impl + &source) + #endif + { + node_ptr it (node_algorithms::begin_node(source.header_ptr())) + , itend(node_algorithms::end_node (source.header_ptr())); + + while(it != itend){ + node_ptr const p(it); + BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(!safemode_or_autounlink || !node_algorithms::unique(p)); + it = node_algorithms::next_node(it); + if( node_algorithms::transfer_unique(this->header_ptr(), this->key_node_comp(this->key_comp()), source.header_ptr(), p) ){ + source.sz_traits().decrement(); + this->sz_traits().increment(); + } + } + } + + //! Requires: "source" container's Options can only can differ in the comparison + //! function from *this. + //! + //! Effects: Extracts each element in source and insert it into a using + //! the comparison object of *this. + //! + //! Postcondition: Pointers and references to the transferred elements of source refer + //! to those same elements but as members of *this. Iterators referring to the transferred + //! elements will continue to refer to their elements, but they now behave as iterators into *this, + //! not into source. + //! + //! Throws: Nothing unless the comparison object throws. + //! + //! Complexity: N log(a.size() + N) (N has the value source.size()) + #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) + template void merge_equal(bstree &); + #else + template + void merge_equal(bstree_impl + &source) + #endif + { + node_ptr it (node_algorithms::begin_node(source.header_ptr())) + , itend(node_algorithms::end_node (source.header_ptr())); + + while(it != itend){ + node_ptr const p(it); + BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(!safemode_or_autounlink || !node_algorithms::unique(p)); + it = node_algorithms::next_node(it); + node_algorithms::transfer_equal(this->header_ptr(), this->key_node_comp(this->key_comp()), source.header_ptr(), p); + source.sz_traits().decrement(); + this->sz_traits().increment(); + } + } + //! Effects: Asserts the integrity of the container with additional checks provided by the user. //! //! Complexity: Linear time. diff --git a/include/boost/intrusive/bstree_algorithms.hpp b/include/boost/intrusive/bstree_algorithms.hpp index 7e01eb7..e8caee0 100644 --- a/include/boost/intrusive/bstree_algorithms.hpp +++ b/include/boost/intrusive/bstree_algorithms.hpp @@ -1319,6 +1319,43 @@ class bstree_algorithms : public bstree_algorithms_base erase(header, z, ignored); } + //! Requires: header1 and header2 must be the headers of trees tree1 and tree2 + //! respectively, z a non-header node of tree1. NodePtrCompare is the comparison + //! function of tree1.. + //! + //! Effects: Transfers node "z" from tree1 to tree2 if tree1 does not contain + //! a node that is equivalent to z. + //! + //! Returns: True if the node was trasferred, false otherwise. + //! + //! Complexity: Logarithmic. + //! + //! Throws: If the comparison throws. + template + BOOST_INTRUSIVE_FORCEINLINE static bool transfer_unique + (const node_ptr & header1, NodePtrCompare comp, const node_ptr &header2, const node_ptr & z) + { + data_for_rebalance ignored; + return transfer_unique(header1, comp, header2, z, ignored); + } + + //! Requires: header1 and header2 must be the headers of trees tree1 and tree2 + //! respectively, z a non-header node of tree1. NodePtrCompare is the comparison + //! function of tree1.. + //! + //! Effects: Transfers node "z" from tree1 to tree2. + //! + //! Complexity: Logarithmic. + //! + //! Throws: If the comparison throws. + template + BOOST_INTRUSIVE_FORCEINLINE static void transfer_equal + (const node_ptr & header1, NodePtrCompare comp, const node_ptr &header2, const node_ptr & z) + { + data_for_rebalance ignored; + transfer_equal(header1, comp, header2, z, ignored); + } + //! Requires: node is a tree node but not the header. //! //! Effects: Unlinks the node and rebalances the tree. @@ -1433,6 +1470,30 @@ class bstree_algorithms : public bstree_algorithms_base } protected: + + template + static bool transfer_unique + (const node_ptr & header1, NodePtrCompare comp, const node_ptr &header2, const node_ptr & z, data_for_rebalance &info) + { + insert_commit_data commit_data; + bool const transferable = insert_unique_check(header1, z, comp, commit_data).second; + if(transferable){ + erase(header2, z, info); + insert_commit(header1, z, commit_data); + } + return transferable; + } + + template + static void transfer_equal + (const node_ptr & header1, NodePtrCompare comp, const node_ptr &header2, const node_ptr & z, data_for_rebalance &info) + { + insert_commit_data commit_data; + insert_equal_upper_bound_check(header1, z, comp, commit_data); + erase(header2, z, info); + insert_commit(header1, z, commit_data); + } + static void erase(const node_ptr & header, const node_ptr & z, data_for_rebalance &info) { node_ptr y(z); diff --git a/include/boost/intrusive/rbtree.hpp b/include/boost/intrusive/rbtree.hpp index 276362d..698de0f 100644 --- a/include/boost/intrusive/rbtree.hpp +++ b/include/boost/intrusive/rbtree.hpp @@ -430,6 +430,14 @@ class rbtree_impl //! @copydoc ::boost::intrusive::bstree::remove_node void remove_node(reference value); + //! @copydoc ::boost::intrusive::bstree::merge_unique(bstree&) + template + void merge_unique(rbtree &); + + //! @copydoc ::boost::intrusive::bstree::merge_equal(bstree&) + template + void merge_equal(rbtree &); + friend bool operator< (const rbtree_impl &x, const rbtree_impl &y); friend bool operator==(const rbtree_impl &x, const rbtree_impl &y); diff --git a/include/boost/intrusive/rbtree_algorithms.hpp b/include/boost/intrusive/rbtree_algorithms.hpp index 2a74e1b..6a7c563 100644 --- a/include/boost/intrusive/rbtree_algorithms.hpp +++ b/include/boost/intrusive/rbtree_algorithms.hpp @@ -284,22 +284,35 @@ class rbtree_algorithms { typename bstree_algo::data_for_rebalance info; bstree_algo::erase(header, z, info); - - color new_z_color; - if(info.y != z){ - new_z_color = NodeTraits::get_color(info.y); - NodeTraits::set_color(info.y, NodeTraits::get_color(z)); - } - else{ - new_z_color = NodeTraits::get_color(z); - } - //Rebalance rbtree if needed - if(new_z_color != NodeTraits::red()){ - rebalance_after_erasure(header, info.x, info.x_parent); - } + rebalance_after_erasure(header, z, info); return z; } + //! @copydoc ::boost::intrusive::bstree_algorithms::transfer_unique + template + static bool transfer_unique + (const node_ptr & header1, NodePtrCompare comp, const node_ptr &header2, const node_ptr & z) + { + typename bstree_algo::data_for_rebalance info; + bool const transferred = bstree_algo::transfer_unique(header1, comp, header2, z, info); + if(transferred){ + rebalance_after_erasure(header2, z, info); + rebalance_after_insertion(header1, z); + } + return transferred; + } + + //! @copydoc ::boost::intrusive::bstree_algorithms::transfer_equal + template + static void transfer_equal + (const node_ptr & header1, NodePtrCompare comp, const node_ptr &header2, const node_ptr & z) + { + typename bstree_algo::data_for_rebalance info; + bstree_algo::transfer_equal(header1, comp, header2, z, info); + rebalance_after_erasure(header2, z, info); + rebalance_after_insertion(header1, z); + } + //! @copydoc ::boost::intrusive::bstree_algorithms::clone(const const_node_ptr&,const node_ptr&,Cloner,Disposer) template static void clone @@ -431,7 +444,24 @@ class rbtree_algorithms /// @cond private: - static void rebalance_after_erasure(const node_ptr & header, node_ptr x, node_ptr x_parent) + static void rebalance_after_erasure + ( const node_ptr & header, const node_ptr &z, const typename bstree_algo::data_for_rebalance &info) + { + color new_z_color; + if(info.y != z){ + new_z_color = NodeTraits::get_color(info.y); + NodeTraits::set_color(info.y, NodeTraits::get_color(z)); + } + else{ + new_z_color = NodeTraits::get_color(z); + } + //Rebalance rbtree if needed + if(new_z_color != NodeTraits::red()){ + rebalance_after_erasure_restore_invariants(header, info.x, info.x_parent); + } + } + + static void rebalance_after_erasure_restore_invariants(const node_ptr & header, node_ptr x, node_ptr x_parent) { while(1){ if(x_parent == header || (x && NodeTraits::get_color(x) != NodeTraits::black())){ diff --git a/include/boost/intrusive/set.hpp b/include/boost/intrusive/set.hpp index 36c46c7..9b9a963 100644 --- a/include/boost/intrusive/set.hpp +++ b/include/boost/intrusive/set.hpp @@ -28,6 +28,11 @@ namespace boost { namespace intrusive { +#if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) +template +class multiset_impl; +#endif + //! The class template set is an intrusive container, that mimics most of //! the interface of std::set as described in the C++ standard. //! @@ -399,6 +404,26 @@ class set_impl //! @copydoc ::boost::intrusive::rbtree::remove_node void remove_node(reference value); + + //! @copydoc ::boost::intrusive::rbtree::merge_unique + template + void merge(set &source); + + //! @copydoc ::boost::intrusive::rbtree::merge_unique + template + void merge(multiset &source); + + #else + + template + void merge(set_impl &source) + { return tree_type::merge_unique(source); } + + + template + void merge(multiset_impl &source) + { return tree_type::merge_unique(source); } + #endif //#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED }; @@ -865,6 +890,25 @@ class multiset_impl //! @copydoc ::boost::intrusive::rbtree::remove_node void remove_node(reference value); + + //! @copydoc ::boost::intrusive::rbtree::merge_equal + template + void merge(multiset &source); + + //! @copydoc ::boost::intrusive::rbtree::merge_equal + template + void merge(set &source); + + #else + + template + void merge(multiset_impl &source) + { return tree_type::merge_equal(source); } + + template + void merge(set_impl &source) + { return tree_type::merge_equal(source); } + #endif //#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED }; diff --git a/include/boost/intrusive/sg_set.hpp b/include/boost/intrusive/sg_set.hpp index 171bd59..8e1bfcc 100644 --- a/include/boost/intrusive/sg_set.hpp +++ b/include/boost/intrusive/sg_set.hpp @@ -26,6 +26,11 @@ namespace boost { namespace intrusive { +#if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) +template +class sg_multiset_impl; +#endif + //! The class template sg_set is an intrusive container, that mimics most of //! the interface of std::sg_set as described in the C++ standard. //! @@ -410,6 +415,24 @@ class sg_set_impl //! @copydoc ::boost::intrusive::sgtree::balance_factor(float) void balance_factor(float new_alpha); + //! @copydoc ::boost::intrusive::rbtree::merge_unique + template + void merge(sg_set &source); + + //! @copydoc ::boost::intrusive::rbtree::merge_unique + template + void merge(sg_multiset &source); + + #else + + template + void merge(sg_set_impl &source) + { return tree_type::merge_unique(source); } + + template + void merge(sg_multiset_impl &source) + { return tree_type::merge_unique(source); } + #endif //#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED }; @@ -889,6 +912,24 @@ class sg_multiset_impl //! @copydoc ::boost::intrusive::sgtree::balance_factor(float) void balance_factor(float new_alpha); + //! @copydoc ::boost::intrusive::treap::merge_unique + template + void merge(sg_multiset &source); + + //! @copydoc ::boost::intrusive::treap::merge_unique + template + void merge(sg_set &source); + + #else + + template + void merge(sg_multiset_impl &source) + { return tree_type::merge_equal(source); } + + template + void merge(sg_set_impl &source) + { return tree_type::merge_equal(source); } + #endif //#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED }; diff --git a/include/boost/intrusive/sgtree.hpp b/include/boost/intrusive/sgtree.hpp index 6e7af7d..c82551f 100644 --- a/include/boost/intrusive/sgtree.hpp +++ b/include/boost/intrusive/sgtree.hpp @@ -696,6 +696,66 @@ class sgtree_impl this->max_tree_size_ = 0; } + #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) + //! @copydoc ::boost::intrusive::bstree::merge_unique + template void merge_unique(sgtree &); + #else + template + void merge_unique(sgtree_impl + &source) + #endif + { + node_ptr it (node_algorithms::begin_node(source.header_ptr())) + , itend(node_algorithms::end_node (source.header_ptr())); + + while(it != itend){ + node_ptr const p(it); + BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(!safemode_or_autounlink || !node_algorithms::unique(p)); + it = node_algorithms::next_node(it); + + std::size_t max_tree1_size = this->max_tree_size_; + std::size_t max_tree2_size = source.max_tree_size_; + if( node_algorithms::transfer_unique + ( this->header_ptr(), this->key_node_comp(this->key_comp()), this->size(), max_tree1_size + , source.header_ptr(), p, source.size(), max_tree2_size + , this->get_h_alpha_func(), this->get_alpha_by_max_size_func()) ){ + this->max_tree_size_ = (size_type)max_tree1_size; + this->sz_traits().increment(); + source.max_tree_size_ = (size_type)max_tree2_size; + source.sz_traits().decrement(); + } + } + } + + #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) + //! @copydoc ::boost::intrusive::bstree::merge_equal + template void merge_equal(sgtree &); + #else + template + void merge_equal(sgtree_impl + &source) + #endif + { + node_ptr it (node_algorithms::begin_node(source.header_ptr())) + , itend(node_algorithms::end_node (source.header_ptr())); + + while(it != itend){ + node_ptr const p(it); + BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(!safemode_or_autounlink || !node_algorithms::unique(p)); + it = node_algorithms::next_node(it); + std::size_t max_tree1_size = this->max_tree_size_; + std::size_t max_tree2_size = source.max_tree_size_; + node_algorithms::transfer_equal + ( this->header_ptr(), this->key_node_comp(this->key_comp()), this->size(), max_tree1_size + , source.header_ptr(), p, source.size(), max_tree2_size + , this->get_h_alpha_func(), this->get_alpha_by_max_size_func()); + this->max_tree_size_ = (size_type)max_tree1_size; + this->sz_traits().increment(); + source.max_tree_size_ = (size_type)max_tree2_size; + source.sz_traits().decrement(); + } + } + #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED //! @copydoc ::boost::intrusive::bstree::count(const key_type &)const size_type count(const key_type &key) const; diff --git a/include/boost/intrusive/sgtree_algorithms.hpp b/include/boost/intrusive/sgtree_algorithms.hpp index 2d74184..e6002a7 100644 --- a/include/boost/intrusive/sgtree_algorithms.hpp +++ b/include/boost/intrusive/sgtree_algorithms.hpp @@ -138,7 +138,6 @@ class sgtree_algorithms template static node_ptr erase(const node_ptr & header, const node_ptr & z, std::size_t tree_size, std::size_t &max_tree_size, AlphaByMaxSize alpha_by_maxsize) { - //typename bstree_algo::data_for_rebalance info; bstree_algo::erase(header, z); --tree_size; if (tree_size > 0 && @@ -288,12 +287,38 @@ class sgtree_algorithms //! @copydoc ::boost::intrusive::bstree_algorithms::insert_unique_commit(const node_ptr&,const node_ptr&,const insert_commit_data&) template - static void insert_unique_commit + BOOST_INTRUSIVE_FORCEINLINE static void insert_unique_commit (const node_ptr & header, const node_ptr & new_value, const insert_commit_data &commit_data ,std::size_t tree_size, H_Alpha h_alpha, std::size_t &max_tree_size) + { return insert_commit(header, new_value, commit_data, tree_size, h_alpha, max_tree_size); } + + //! @copydoc ::boost::intrusive::bstree_algorithms::transfer_unique + template + static bool transfer_unique + ( const node_ptr & header1, NodePtrCompare comp, std::size_t tree1_size, std::size_t &max_tree1_size + , const node_ptr &header2, const node_ptr & z, std::size_t tree2_size, std::size_t &max_tree2_size + ,H_Alpha h_alpha, AlphaByMaxSize alpha_by_maxsize) { - bstree_algo::insert_unique_commit(header, new_value, commit_data); - rebalance_after_insertion(new_value, commit_data.depth, tree_size+1, h_alpha, max_tree_size); + insert_commit_data commit_data; + bool const transferable = insert_unique_check(header1, z, comp, commit_data).second; + if(transferable){ + erase(header2, z, tree2_size, max_tree2_size, alpha_by_maxsize); + insert_commit(header1, z, commit_data, tree1_size, h_alpha, max_tree1_size); + } + return transferable; + } + + //! @copydoc ::boost::intrusive::bstree_algorithms::transfer_equal + template + static void transfer_equal + ( const node_ptr & header1, NodePtrCompare comp, std::size_t tree1_size, std::size_t &max_tree1_size + , const node_ptr &header2, const node_ptr & z, std::size_t tree2_size, std::size_t &max_tree2_size + ,H_Alpha h_alpha, AlphaByMaxSize alpha_by_maxsize) + { + insert_commit_data commit_data; + insert_equal_upper_bound_check(header1, z, comp, commit_data); + erase(header2, z, tree2_size, max_tree2_size, alpha_by_maxsize); + insert_commit(header1, z, commit_data, tree1_size, h_alpha, max_tree1_size); } #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED @@ -310,6 +335,25 @@ class sgtree_algorithms /// @cond private: + template + static void insert_equal_upper_bound_check + (const node_ptr & header, const KeyType &key + ,KeyNodePtrCompare comp, insert_commit_data &commit_data) + { + std::size_t depth; + bstree_algo::insert_equal_upper_bound_check(header, key, comp, commit_data, &depth); + commit_data.depth = depth; + } + + template + static void insert_commit + (const node_ptr & header, const node_ptr & new_value, const insert_commit_data &commit_data + ,std::size_t tree_size, H_Alpha h_alpha, std::size_t &max_tree_size) + { + bstree_algo::insert_unique_commit(header, new_value, commit_data); + rebalance_after_insertion(new_value, commit_data.depth, tree_size+1, h_alpha, max_tree_size); + } + template static void rebalance_after_insertion (const node_ptr &x, std::size_t depth diff --git a/include/boost/intrusive/splay_set.hpp b/include/boost/intrusive/splay_set.hpp index 893b580..e63a027 100644 --- a/include/boost/intrusive/splay_set.hpp +++ b/include/boost/intrusive/splay_set.hpp @@ -23,6 +23,11 @@ # pragma once #endif +#if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) +template +class splay_multiset_impl; +#endif + namespace boost { namespace intrusive { @@ -420,6 +425,26 @@ class splay_set_impl //! @copydoc ::boost::intrusive::splaytree::rebalance_subtree iterator rebalance_subtree(iterator root); + + //! @copydoc ::boost::intrusive::splaytree::merge_unique + template + void merge(splay_set &source); + + //! @copydoc ::boost::intrusive::splaytree::merge_unique + template + void merge(splay_multiset &source); + + #else + + template + void merge(splay_set_impl &source) + { return tree_type::merge_unique(source); } + + + template + void merge(splay_multiset_impl &source) + { return tree_type::merge_unique(source); } + #endif //#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED }; @@ -902,6 +927,25 @@ class splay_multiset_impl //! @copydoc ::boost::intrusive::splaytree::rebalance_subtree iterator rebalance_subtree(iterator root); + + //! @copydoc ::boost::intrusive::splaytree::merge_equal + template + void merge(splay_multiset &source); + + //! @copydoc ::boost::intrusive::splaytree::merge_equal + template + void merge(splay_set &source); + + #else + + template + void merge(splay_multiset_impl &source) + { return tree_type::merge_equal(source); } + + template + void merge(splay_set_impl &source) + { return tree_type::merge_equal(source); } + #endif //#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED }; diff --git a/include/boost/intrusive/splaytree.hpp b/include/boost/intrusive/splaytree.hpp index afc1081..1904e57 100644 --- a/include/boost/intrusive/splaytree.hpp +++ b/include/boost/intrusive/splaytree.hpp @@ -454,6 +454,14 @@ class splaytree_impl //! @copydoc ::boost::intrusive::bstree::remove_node void remove_node(reference value); + //! @copydoc ::boost::intrusive::bstree::merge_unique(bstree&) + template + void merge_unique(splaytree &); + + //! @copydoc ::boost::intrusive::bstree::merge_equal(bstree&) + template + void merge_equal(splaytree &); + #endif //#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED //! Requires: i must be a valid iterator of *this. diff --git a/include/boost/intrusive/splaytree_algorithms.hpp b/include/boost/intrusive/splaytree_algorithms.hpp index 1c6afdf..be2e182 100644 --- a/include/boost/intrusive/splaytree_algorithms.hpp +++ b/include/boost/intrusive/splaytree_algorithms.hpp @@ -251,6 +251,33 @@ class splaytree_algorithms bstree_algo::erase(header, z); } + //! @copydoc ::boost::intrusive::bstree_algorithms::transfer_unique + template + static bool transfer_unique + (const node_ptr & header1, NodePtrCompare comp, const node_ptr &header2, const node_ptr & z) + { + typename bstree_algo::insert_commit_data commit_data; + bool const transferable = bstree_algo::insert_unique_check(header1, z, comp, commit_data).second; + if(transferable){ + erase(header2, z); + bstree_algo::insert_commit(header1, z, commit_data); + splay_up(z, header1); + } + return transferable; + } + + //! @copydoc ::boost::intrusive::bstree_algorithms::transfer_equal + template + static void transfer_equal + (const node_ptr & header1, NodePtrCompare comp, const node_ptr &header2, const node_ptr & z) + { + insert_commit_data commit_data; + splay_down(header1, z, comp); + bstree_algo::insert_equal_upper_bound_check(header1, z, comp, commit_data); + erase(header2, z); + bstree_algo::insert_commit(header1, z, commit_data); + } + #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED //! @copydoc ::boost::intrusive::bstree_algorithms::clone(const const_node_ptr&,const node_ptr&,Cloner,Disposer) template diff --git a/include/boost/intrusive/treap.hpp b/include/boost/intrusive/treap.hpp index 3852719..aeef64c 100644 --- a/include/boost/intrusive/treap.hpp +++ b/include/boost/intrusive/treap.hpp @@ -997,6 +997,56 @@ class treap_impl this->tree_type::sz_traits().set_size(0); } + #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) + //! @copydoc ::boost::intrusive::bstree::merge_unique + template void merge_unique(sgtree &); + #else + template + void merge_unique(treap_impl + &source) + #endif + { + node_ptr it (node_algorithms::begin_node(source.header_ptr())) + , itend(node_algorithms::end_node (source.header_ptr())); + + while(it != itend){ + node_ptr const p(it); + BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(!safemode_or_autounlink || !node_algorithms::unique(p)); + it = node_algorithms::next_node(it); + + if( node_algorithms::transfer_unique + ( this->header_ptr(), this->key_node_comp(this->key_comp()) + , this->key_node_prio_comp(this->priv_pcomp()), source.header_ptr(), p) ){ + this->sz_traits().increment(); + source.sz_traits().decrement(); + } + } + } + + #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) + //! @copydoc ::boost::intrusive::bstree::merge_equal(bstree&) + template void merge_equal(sgtree &); + #else + template + void merge_equal(treap_impl + &source) + #endif + { + node_ptr it (node_algorithms::begin_node(source.header_ptr())) + , itend(node_algorithms::end_node (source.header_ptr())); + + while(it != itend){ + node_ptr const p(it); + BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(!safemode_or_autounlink || !node_algorithms::unique(p)); + it = node_algorithms::next_node(it); + node_algorithms::transfer_equal + ( this->header_ptr(), this->key_node_comp(this->key_comp()) + , this->key_node_prio_comp(this->priv_pcomp()), source.header_ptr(), p); + this->sz_traits().increment(); + source.sz_traits().decrement(); + } + } + //! @copydoc ::boost::intrusive::bstree::check(ExtraChecker)const template void check(ExtraChecker extra_checker) const diff --git a/include/boost/intrusive/treap_algorithms.hpp b/include/boost/intrusive/treap_algorithms.hpp index 006a880..b1a82b3 100644 --- a/include/boost/intrusive/treap_algorithms.hpp +++ b/include/boost/intrusive/treap_algorithms.hpp @@ -569,6 +569,34 @@ class treap_algorithms rotate_up_n(header, new_node, commit_data.rotations); } + //! @copydoc ::boost::intrusive::bstree_algorithms::transfer_unique + template + static bool transfer_unique + (const node_ptr & header1, NodePtrCompare comp, KeyNodePtrPrioCompare pcomp, const node_ptr &header2, const node_ptr & z) + { + insert_commit_data commit_data; + bool const transferable = insert_unique_check(header1, z, comp, pcomp, commit_data).second; + if(transferable){ + erase(header2, z, pcomp); + insert_unique_commit(header1, z, commit_data); + } + return transferable; + } + + //! @copydoc ::boost::intrusive::bstree_algorithms::transfer_equal + template + static void transfer_equal + (const node_ptr & header1, NodePtrCompare comp, KeyNodePtrPrioCompare pcomp, const node_ptr &header2, const node_ptr & z) + { + insert_commit_data commit_data; + bstree_algo::insert_equal_upper_bound_check(header1, z, comp, commit_data); + rebalance_after_insertion_check(header1, commit_data.node, z, pcomp, commit_data.rotations); + rebalance_for_erasure(header2, z, pcomp); + bstree_algo::erase(header2, z); + bstree_algo::insert_unique_commit(header1, z, commit_data); + rotate_up_n(header1, z, commit_data.rotations); + } + #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED //! @copydoc ::boost::intrusive::bstree_algorithms::is_header diff --git a/include/boost/intrusive/treap_set.hpp b/include/boost/intrusive/treap_set.hpp index f97b376..0c4e2d0 100644 --- a/include/boost/intrusive/treap_set.hpp +++ b/include/boost/intrusive/treap_set.hpp @@ -26,6 +26,11 @@ namespace boost { namespace intrusive { +#if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) +template +class treap_multiset_impl; +#endif + //! The class template treap_set is an intrusive container, that mimics most of //! the interface of std::set as described in the C++ standard. //! @@ -229,7 +234,7 @@ class treap_set_impl iterator insert(const_iterator hint, reference value) { return tree_type::insert_unique(hint, value); } - //! @copydoc ::boost::intrusive::treap::insert_unique_check(const key_type,insert_commit_data&) + //! @copydoc ::boost::intrusive::treap::insert_unique_check(const key_type&,insert_commit_data&) std::pair insert_check( const key_type &key, insert_commit_data &commit_data) { return tree_type::insert_unique_check(key, commit_data); } @@ -429,6 +434,25 @@ class treap_set_impl //! @copydoc ::boost::intrusive::treap::remove_node void remove_node(reference value); + + //! @copydoc ::boost::intrusive::treap::merge_unique + template + void merge(treap_set &source); + + //! @copydoc ::boost::intrusive::treap::merge_unique + template + void merge(treap_multiset &source); + + #else + + template + void merge(treap_set_impl &source) + { return tree_type::merge_unique(source); } + + template + void merge(treap_multiset_impl &source) + { return tree_type::merge_unique(source); } + #endif //#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED }; @@ -914,6 +938,24 @@ class treap_multiset_impl //! @copydoc ::boost::intrusive::treap::remove_node void remove_node(reference value); + //! @copydoc ::boost::intrusive::treap::merge_unique + template + void merge(treap_multiset &source); + + //! @copydoc ::boost::intrusive::treap::merge_unique + template + void merge(treap_set &source); + + #else + + template + void merge(treap_multiset_impl &source) + { return tree_type::merge_equal(source); } + + template + void merge(treap_set_impl &source) + { return tree_type::merge_equal(source); } + #endif //#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED }; diff --git a/test/avl_multiset_test.cpp b/test/avl_multiset_test.cpp index 4a40391..c2dce57 100644 --- a/test/avl_multiset_test.cpp +++ b/test/avl_multiset_test.cpp @@ -23,6 +23,7 @@ template < class ValueTraits, bool ConstantTimeSize, bool DefaultHolder, bool Ma struct rebinder { typedef tree_rebinder_common common_t; + typedef typename ValueContainer< typename ValueTraits::value_type >::type value_cont_type; template < class Option1 =void , class Option2 =void @@ -66,8 +67,7 @@ class test_main_template::type base_hook_t; test::test_generic_multiset - < base_hook_t - , rebinder + < rebinder >::test_all(); } }; @@ -86,8 +86,7 @@ class test_main_template::type member_hook_t; test::test_generic_multiset - < member_hook_t - , rebinder + < rebinder >::test_all(); } }; @@ -101,8 +100,7 @@ class test_main_template > testval_traits_t; //nonmember test::test_generic_multiset - < typename testval_traits_t::nonhook_value_traits - , rebinder + < rebinder >::test_all(); } }; @@ -117,8 +115,7 @@ struct test_main_template_bptr bounded_allocator_scope bounded_scope; (void)bounded_scope; test::test_generic_multiset - < value_traits - , rebinder< value_traits, ConstantTimeSize, true, Map> + < rebinder< value_traits, ConstantTimeSize, true, Map> >::test_all(); } }; diff --git a/test/avl_set_test.cpp b/test/avl_set_test.cpp index 99ed28f..677232b 100644 --- a/test/avl_set_test.cpp +++ b/test/avl_set_test.cpp @@ -23,6 +23,7 @@ template < class ValueTraits, bool ConstantTimeSize, bool DefaultHolder, bool Ma struct rebinder { typedef tree_rebinder_common common_t; + typedef typename ValueContainer< typename ValueTraits::value_type >::type value_cont_type; template < class Option1 =void , class Option2 =void @@ -66,8 +67,7 @@ class test_main_template::type base_hook_t; test::test_generic_set - < base_hook_t - , rebinder + < rebinder >::test_all(); } }; @@ -86,8 +86,7 @@ class test_main_template::type member_hook_t; test::test_generic_set - < member_hook_t - , rebinder + < rebinder >::test_all(); } }; @@ -101,8 +100,7 @@ class test_main_template > testval_traits_t; //nonmember test::test_generic_set - < typename testval_traits_t::nonhook_value_traits - , rebinder + < rebinder >::test_all(); } }; @@ -117,8 +115,7 @@ struct test_main_template_bptr bounded_allocator_scope bounded_scope; (void)bounded_scope; test::test_generic_set - < value_traits - , rebinder< value_traits, ConstantTimeSize, true, Map> + < rebinder< value_traits, ConstantTimeSize, true, Map> >::test_all(); } }; diff --git a/test/bs_multiset_test.cpp b/test/bs_multiset_test.cpp index 1786c0d..beb9115 100644 --- a/test/bs_multiset_test.cpp +++ b/test/bs_multiset_test.cpp @@ -22,6 +22,7 @@ template < class ValueTraits, bool ConstantTimeSize, bool DefaultHolder, bool Ma struct rebinder { typedef tree_rebinder_common common_t; + typedef typename ValueContainer< typename ValueTraits::value_type >::type value_cont_type; template < class Option1 =void , class Option2 =void @@ -65,8 +66,7 @@ class test_main_template::type base_hook_t; test::test_generic_multiset - < base_hook_t - , rebinder + < rebinder >::test_all(); } }; @@ -85,8 +85,7 @@ class test_main_template::type member_hook_t; test::test_generic_multiset - < member_hook_t - , rebinder + < rebinder >::test_all(); } }; @@ -101,8 +100,7 @@ class test_main_template > testval_traits_t; //nonmember test::test_generic_multiset - < typename testval_traits_t::nonhook_value_traits - , rebinder + < rebinder >::test_all(); } }; @@ -117,8 +115,7 @@ struct test_main_template_bptr bounded_allocator_scope bounded_scope; (void)bounded_scope; test::test_generic_multiset - < value_traits - , rebinder< value_traits, ConstantTimeSize, true, Map> + < rebinder< value_traits, ConstantTimeSize, true, Map> >::test_all(); } }; diff --git a/test/bs_set_test.cpp b/test/bs_set_test.cpp index 879b25f..d2f4f4f 100644 --- a/test/bs_set_test.cpp +++ b/test/bs_set_test.cpp @@ -22,6 +22,7 @@ template < class ValueTraits, bool ConstantTimeSize, bool DefaultHolder, bool Ma struct rebinder { typedef tree_rebinder_common common_t; + typedef typename ValueContainer< typename ValueTraits::value_type >::type value_cont_type; template < class Option1 =void , class Option2 =void @@ -65,8 +66,7 @@ class test_main_template::type base_hook_t; test::test_generic_set - < base_hook_t - , rebinder + < rebinder >::test_all(); } }; @@ -85,8 +85,7 @@ class test_main_template::type member_hook_t; test::test_generic_set - < member_hook_t - , rebinder + < rebinder >::test_all(); } }; @@ -100,8 +99,7 @@ class test_main_template > testval_traits_t; //nonmember test::test_generic_set - < typename testval_traits_t::nonhook_value_traits - , rebinder + < rebinder >::test_all(); } }; @@ -116,8 +114,7 @@ struct test_main_template_bptr bounded_allocator_scope bounded_scope; (void)bounded_scope; test::test_generic_set - < value_traits - , rebinder< value_traits, ConstantTimeSize, true, Map> + < rebinder< value_traits, ConstantTimeSize, true, Map> >::test_all(); } }; diff --git a/test/generic_assoc_test.hpp b/test/generic_assoc_test.hpp index 96d261b..5c64b4f 100644 --- a/test/generic_assoc_test.hpp +++ b/test/generic_assoc_test.hpp @@ -32,16 +32,10 @@ BOOST_INTRUSIVE_HAS_MEMBER_FUNC_CALLED(has_insert_before, insert_before) BOOST_INTRUSIVE_HAS_MEMBER_FUNC_CALLED(is_treap, priority_comp) -template +template struct test_generic_assoc { - typedef typename ValueTraits::value_type value_type; - typedef typename ValueTraits::pointer pointer; - typedef typename ValueTraits::const_pointer const_pointer; - typedef typename ValueContainer< value_type >::type value_cont_type; - typedef typename pointer_traits::reference reference; - typedef typename pointer_traits - ::reference const_reference; + typedef typename ContainerDefiner::value_cont_type value_cont_type; static void test_all(value_cont_type&); static void test_clone(value_cont_type&); @@ -60,8 +54,8 @@ struct test_generic_assoc static void test_container_from_iterator(value_cont_type&, detail::false_type) {} }; -template -void test_generic_assoc:: +template +void test_generic_assoc:: test_container_from_iterator(value_cont_type& values, detail::true_type) { typedef typename ContainerDefiner::template container @@ -84,8 +78,8 @@ void test_generic_assoc:: } } -template -void test_generic_assoc::test_insert_erase_burst() +template +void test_generic_assoc::test_insert_erase_burst() { //value_cont_type values; const std::size_t MaxValues = 200; @@ -136,8 +130,8 @@ void test_generic_assoc::test_insert_erase_burst( } } -template -void test_generic_assoc::test_all(value_cont_type& values) +template +void test_generic_assoc::test_all(value_cont_type& values) { typedef typename ContainerDefiner::template container <>::type assoc_type; @@ -151,17 +145,20 @@ void test_generic_assoc::test_all(value_cont_type test_container_from_iterator(values, detail::bool_< assoc_type::has_container_from_iterator >()); } -template -void test_generic_assoc +template +void test_generic_assoc ::test_clone(value_cont_type& values) { { typedef typename ContainerDefiner::template container <>::type assoc_type; + typedef typename assoc_type::value_type value_type; + typedef typename assoc_type::size_type size_type; + assoc_type testset1 (values.begin(), values.begin() + values.size()); assoc_type testset2; - typedef typename assoc_type::size_type size_type; + size_type const testset1_oldsize = testset1.size(); testset2.clone_from(testset1, test::new_cloner(), test::delete_disposer()); BOOST_TEST (testset1.size() == testset1_oldsize); @@ -177,8 +174,8 @@ void test_generic_assoc } } -template -void test_generic_assoc +template +void test_generic_assoc ::test_container_from_end(value_cont_type& values, detail::true_type) { typedef typename ContainerDefiner::template container @@ -188,8 +185,8 @@ void test_generic_assoc BOOST_TEST (testset == assoc_type::container_from_end_iterator(testset.cend())); } -template -void test_generic_assoc::test_splay_up +template +void test_generic_assoc::test_splay_up (value_cont_type& values, detail::true_type) { typedef typename ContainerDefiner::template container @@ -223,8 +220,8 @@ void test_generic_assoc::test_splay_up } } -template -void test_generic_assoc::test_splay_down +template +void test_generic_assoc::test_splay_down (value_cont_type& values, detail::true_type) { typedef typename ContainerDefiner::template container @@ -259,8 +256,8 @@ void test_generic_assoc::test_splay_down } } -template -void test_generic_assoc::test_rebalance +template +void test_generic_assoc::test_rebalance (value_cont_type& values, detail::true_type) { typedef typename ContainerDefiner::template container @@ -294,8 +291,8 @@ void test_generic_assoc::test_rebalance } } -template -void test_generic_assoc::test_insert_before +template +void test_generic_assoc::test_insert_before (value_cont_type& values, detail::true_type) { typedef typename ContainerDefiner::template container diff --git a/test/generic_multiset_test.hpp b/test/generic_multiset_test.hpp index 00bb704..ba86bfc 100644 --- a/test/generic_multiset_test.hpp +++ b/test/generic_multiset_test.hpp @@ -25,27 +25,22 @@ namespace boost{ namespace intrusive{ namespace test{ -template +template struct test_generic_multiset { - typedef typename ValueTraits::value_type value_type; - typedef typename ValueTraits::pointer pointer; - typedef typename ValueTraits::const_pointer const_pointer; - typedef typename ValueContainer< value_type >::type value_cont_type; - typedef typename pointer_traits::reference reference; - typedef typename pointer_traits - ::reference const_reference; + typedef typename ContainerDefiner::value_cont_type value_cont_type; static void test_all(); static void test_sort(value_cont_type&); static void test_insert(value_cont_type&); static void test_swap(value_cont_type&); + static void test_merge(value_cont_type&); static void test_find(value_cont_type&); static void test_impl(); }; -template -void test_generic_multiset::test_all () +template +void test_generic_multiset::test_all () { static const int random_init[6] = { 3, 2, 4, 1, 5, 2 }; value_cont_type values (6); @@ -69,14 +64,15 @@ void test_generic_multiset::test_all () test_sort(values); test_insert(values); test_swap(values); + test_merge(values); test_find(values); test_impl(); - test_generic_assoc::test_all(values); + test_generic_assoc::test_all(values); } //test case due to an error in tree implementation: -template -void test_generic_multiset::test_impl() +template +void test_generic_multiset::test_impl() { value_cont_type values (5); for (int i = 0; i < 5; ++i) @@ -97,8 +93,8 @@ void test_generic_multiset::test_impl() } //test: constructor, iterator, clear, reverse_iterator, front, back, size: -template -void test_generic_multiset::test_sort(value_cont_type& values) +template +void test_generic_multiset::test_sort(value_cont_type& values) { typedef typename ContainerDefiner::template container <>::type multiset_type; @@ -123,14 +119,15 @@ void test_generic_multiset::test_sort(value_cont_ } //test: insert, const_iterator, const_reverse_iterator, erase, iterator_to: -template -void test_generic_multiset::test_insert(value_cont_type& values) +template +void test_generic_multiset::test_insert(value_cont_type& values) { typedef typename ContainerDefiner::template container <>::type multiset_type; multiset_type testset; testset.insert(values.begin() + 2, values.begin() + 5); + testset.check(); { int init_values [] = { 1, 4, 5 }; TEST_INTRUSIVE_SEQUENCE( init_values, testset.begin() ); } @@ -138,6 +135,7 @@ void test_generic_multiset::test_insert(value_con BOOST_TEST (i->value_ == 1); i = testset.insert (i, values[0]); + testset.check(); BOOST_TEST (&*i == &values[0]); { int init_values [] = { 5, 4, 3, 1 }; @@ -150,14 +148,15 @@ void test_generic_multiset::test_insert(value_con BOOST_TEST (&*i == &values[2]); testset.erase(i); + testset.check(); { int init_values [] = { 1, 3, 5 }; TEST_INTRUSIVE_SEQUENCE( init_values, testset.begin() ); } } //test: insert (seq-version), swap, erase (seq-version), size: -template -void test_generic_multiset::test_swap(value_cont_type& values) +template +void test_generic_multiset::test_swap(value_cont_type& values) { typedef typename ContainerDefiner::template container <>::type multiset_type; @@ -176,9 +175,50 @@ void test_generic_multiset::test_swap(value_cont_ BOOST_TEST (&*testset1.begin() == &values[3]); } +template +void test_generic_multiset::test_merge(value_cont_type& values) +{ + typedef typename ContainerDefiner::template container + <>::type multiset_type; + typedef typename multiset_type::key_of_value key_of_value; + //original vector: 3, 2, 4, 1, 5, 2 + //2,3 + multiset_type testset1 (values.begin(), values.begin() + 2); + //1, 2, 4, 5 + multiset_type testset2; + testset2.insert (values.begin() + 2, values.begin() + 6); + + testset2.merge(testset1); + testset1.check(); + testset2.check(); + + BOOST_TEST (testset1.empty()); + BOOST_TEST (testset2.size() == 6); + { int init_values [] = { 1, 2, 2, 3, 4, 5 }; + TEST_INTRUSIVE_SEQUENCE( init_values, testset2.begin() ); } + + value_cont_type cmp_val_cont(1); + typename value_cont_type::reference cmp_val = cmp_val_cont.front(); + (&cmp_val)->value_ = 2; + + BOOST_TEST (*testset2.find(key_of_value()(cmp_val)) == values[5]); + BOOST_TEST (&*(++testset2.find(key_of_value()(cmp_val))) == &values[1]); + + testset1.merge(testset2); + testset1.check(); + testset2.check(); + + BOOST_TEST (testset1.size() == 6); + { int init_values [] = { 1, 2, 2, 3, 4, 5 }; + TEST_INTRUSIVE_SEQUENCE( init_values, testset1.begin() ); } + BOOST_TEST (*testset1.find(key_of_value()(cmp_val)) == values[5]); + BOOST_TEST (&*(++testset1.find(key_of_value()(cmp_val))) == &values[1]); + BOOST_TEST (testset2.empty()); +} + //test: find, equal_range (lower_bound, upper_bound): -template -void test_generic_multiset::test_find(value_cont_type& values) +template +void test_generic_multiset::test_find(value_cont_type& values) { typedef typename ContainerDefiner::template container <>::type multiset_type; @@ -189,7 +229,7 @@ void test_generic_multiset::test_find(value_cont_ { value_cont_type cmp_val_cont(1); - reference cmp_val = cmp_val_cont.front(); + typename value_cont_type::reference cmp_val = cmp_val_cont.front(); (&cmp_val)->value_ = 2; iterator i = testset.find (key_of_value()(cmp_val)); BOOST_TEST (i->value_ == 2); @@ -208,8 +248,8 @@ void test_generic_multiset::test_find(value_cont_ std::pair range; std::pair const_range; value_cont_type cmp_val_cont(2); - reference cmp_val_lower = cmp_val_cont.front(); - reference cmp_val_upper = cmp_val_cont.back(); + typename value_cont_type::reference cmp_val_lower = cmp_val_cont.front(); + typename value_cont_type::reference cmp_val_upper = cmp_val_cont.back(); { (&cmp_val_lower)->value_ = 1; (&cmp_val_upper)->value_ = 2; diff --git a/test/generic_set_test.hpp b/test/generic_set_test.hpp index 1369c27..58f46b8 100644 --- a/test/generic_set_test.hpp +++ b/test/generic_set_test.hpp @@ -27,31 +27,25 @@ namespace boost{ namespace intrusive{ namespace test{ -template +template struct test_generic_set { static void test_all(); private: - typedef typename ValueTraits::value_type value_type; - typedef typename ValueTraits::pointer pointer; - typedef typename ValueTraits::const_pointer const_pointer; - typedef typename ValueContainer< value_type >::type value_cont_type; - typedef typename pointer_traits::reference reference; - typedef typename pointer_traits - ::reference const_reference; - + typedef typename ContainerDefiner::value_cont_type value_cont_type; static void test_sort(value_cont_type&); static void test_insert(value_cont_type&); static void test_insert_advanced(value_cont_type&, detail::true_type); static void test_insert_advanced(value_cont_type&, detail::false_type); static void test_swap(value_cont_type&); + static void test_merge(value_cont_type&); static void test_find(value_cont_type&); static void test_impl(); }; -template -void test_generic_set::test_all() +template +void test_generic_set::test_all() { typedef typename ContainerDefiner::template container <>::type set_type; @@ -79,9 +73,10 @@ void test_generic_set::test_all() test_insert(values); test_insert_advanced(values, detail::bool_< is_treap< set_type >::value >()); test_swap(values); + test_merge(values); test_find(values); test_impl(); - test_generic_assoc::test_all(values); + test_generic_assoc::test_all(values); } { value_cont_type values(6); @@ -93,8 +88,8 @@ void test_generic_set::test_all() } //test case due to an error in tree implementation: -template -void test_generic_set::test_impl() +template +void test_generic_set::test_impl() { value_cont_type values (5); for (int i = 0; i < 5; ++i) @@ -115,8 +110,8 @@ void test_generic_set::test_impl() } //test: constructor, iterator, clear, reverse_iterator, front, back, size: -template -void test_generic_set::test_sort(value_cont_type& values) +template +void test_generic_set::test_sort(value_cont_type& values) { typedef typename ContainerDefiner::template container <>::type set_type; @@ -139,14 +134,15 @@ void test_generic_set::test_sort(value_cont_type& } //test: insert, const_iterator, const_reverse_iterator, erase, s_iterator_to: -template -void test_generic_set::test_insert(value_cont_type& values) +template +void test_generic_set::test_insert(value_cont_type& values) { typedef typename ContainerDefiner::template container <>::type set_type; { set_type testset; testset.insert(values.begin() + 2, values.begin() + 5); + testset.check(); const set_type& const_testset = testset; { int init_values [] = { 1, 4, 5 }; @@ -156,6 +152,7 @@ void test_generic_set::test_insert(value_cont_typ BOOST_TEST (i->value_ == 1); i = testset.insert (i, values[0]); + testset.check(); BOOST_TEST (&*i == &values[0]); { int init_values [] = { 5, 4, 3, 1 }; @@ -167,6 +164,7 @@ void test_generic_set::test_insert(value_cont_typ i = set_type::s_iterator_to(values[2]); BOOST_TEST (&*i == &values[2]); + typedef typename value_cont_type::const_reference const_reference; typename set_type::const_iterator ic; ic = testset.iterator_to (static_cast< const_reference >(values[2])); BOOST_TEST (&*ic == &values[2]); @@ -174,6 +172,7 @@ void test_generic_set::test_insert(value_cont_typ BOOST_TEST (&*ic == &values[2]); testset.erase (i); + testset.check(); { int init_values [] = { 1, 3, 5 }; TEST_INTRUSIVE_SEQUENCE( init_values, testset.begin() ); } } @@ -191,8 +190,8 @@ struct prio_comp { return this->priority_compare::operator()(k.int_value(), v.int_value()); } }; -template -void test_generic_set::test_insert_advanced +template +void test_generic_set::test_insert_advanced (value_cont_type& values, detail::true_type) { typedef typename ContainerDefiner::template container @@ -204,6 +203,7 @@ void test_generic_set::test_insert_advanced { set_type testset; testset.insert(values.begin(), values.begin() + values.size()); + testset.check(); value_type v(1); typename set_type::insert_commit_data data; BOOST_TEST ((!testset.insert_check(key_of_value()(v), testset.key_comp(), prio_comp_t(), data).second)); @@ -214,16 +214,18 @@ void test_generic_set::test_insert_advanced } //test: insert, const_iterator, const_reverse_iterator, erase, s_iterator_to: -template -void test_generic_set::test_insert_advanced +template +void test_generic_set::test_insert_advanced (value_cont_type& values, detail::false_type) { typedef typename ContainerDefiner::template container <>::type set_type; typedef typename set_type::key_of_value key_of_value; + typedef typename set_type::value_type value_type; { set_type testset; testset.insert(values.begin(), values.begin() + values.size()); + testset.check(); value_type v(1); typename set_type::insert_commit_data data; BOOST_TEST ((!testset.insert_check(key_of_value()(v), testset.key_comp(), data).second)); @@ -234,8 +236,8 @@ void test_generic_set::test_insert_advanced } //test: insert (seq-version), swap, erase (seq-version), size: -template -void test_generic_set::test_swap(value_cont_type& values) +template +void test_generic_set::test_swap(value_cont_type& values) { typedef typename ContainerDefiner::template container <>::type set_type; @@ -256,9 +258,47 @@ void test_generic_set::test_swap(value_cont_type& BOOST_TEST (&*testset1.begin() == &values[3]); } +template +void test_generic_set::test_merge(value_cont_type& values) +{ + typedef typename ContainerDefiner::template container + <>::type set_type; + //2,3 + set_type testset1 (values.begin(), values.begin() + 2); + //1, 2, 4, 5 + set_type testset2; + testset2.insert (values.begin() + 2, values.begin() + 6); + + testset2.merge(testset1); + testset1.check(); + testset2.check(); + + BOOST_TEST (testset1.size() == 1); + { int init_values [] = { 2 }; + TEST_INTRUSIVE_SEQUENCE( init_values, testset1.begin() ); } + BOOST_TEST (&*testset1.begin() == &values[1]); + + BOOST_TEST (testset2.size() == 5); + { int init_values [] = { 1, 2, 3, 4, 5 }; + TEST_INTRUSIVE_SEQUENCE( init_values, testset2.begin() ); } + + testset1.merge(testset2); + testset1.check(); + testset2.check(); + + BOOST_TEST (testset1.size() == 5); + { int init_values [] = { 1, 2, 3, 4, 5 }; + TEST_INTRUSIVE_SEQUENCE( init_values, testset1.begin() ); } + + BOOST_TEST (testset2.size() == 1); + { int init_values [] = { 2 }; + TEST_INTRUSIVE_SEQUENCE( init_values, testset2.begin() ); } + BOOST_TEST (&*testset2.begin() == &values[5]); +} + //test: find, equal_range (lower_bound, upper_bound), bounded_range: -template -void test_generic_set::test_find(value_cont_type& values) +template +void test_generic_set::test_find(value_cont_type& values) { typedef typename ContainerDefiner::template container <>::type set_type; @@ -266,6 +306,7 @@ void test_generic_set::test_find(value_cont_type& typedef typename set_type::iterator iterator; typedef typename set_type::const_iterator const_iterator; typedef typename set_type::key_of_value key_of_value; + typedef typename value_cont_type::reference reference; { //value_type cmp_val; diff --git a/test/multiset_test.cpp b/test/multiset_test.cpp index fcd6a74..a8ab674 100644 --- a/test/multiset_test.cpp +++ b/test/multiset_test.cpp @@ -23,6 +23,7 @@ template < class ValueTraits, bool ConstantTimeSize, bool DefaultHolder, bool Ma struct rebinder { typedef tree_rebinder_common common_t; + typedef typename ValueContainer< typename ValueTraits::value_type >::type value_cont_type; template < class Option1 =void , class Option2 =void @@ -65,8 +66,7 @@ class test_main_template::type base_hook_t; test::test_generic_multiset - < base_hook_t - , rebinder + < rebinder >::test_all(); } }; @@ -85,8 +85,7 @@ class test_main_template::type member_hook_t; test::test_generic_multiset - < member_hook_t - , rebinder + < rebinder >::test_all(); } }; @@ -100,8 +99,7 @@ class test_main_template > testval_traits_t; //nonmember test::test_generic_multiset - < typename testval_traits_t::nonhook_value_traits - , rebinder + < rebinder >::test_all(); } }; @@ -116,8 +114,7 @@ struct test_main_template_bptr bounded_allocator_scope bounded_scope; (void)bounded_scope; test::test_generic_multiset - < value_traits - , rebinder< value_traits, ConstantTimeSize, true, Map> + < rebinder< value_traits, ConstantTimeSize, true, Map> >::test_all(); } }; diff --git a/test/set_test.cpp b/test/set_test.cpp index 651df47..e72575b 100644 --- a/test/set_test.cpp +++ b/test/set_test.cpp @@ -23,6 +23,7 @@ template < class ValueTraits, bool ConstantTimeSize, bool DefaultHolder, bool Ma struct rebinder { typedef tree_rebinder_common common_t; + typedef typename ValueContainer< typename ValueTraits::value_type >::type value_cont_type; template < class Option1 =void , class Option2 =void @@ -66,8 +67,7 @@ class test_main_template::type base_hook_t; test::test_generic_set - < base_hook_t - , rebinder + < rebinder >::test_all(); } }; @@ -86,8 +86,7 @@ class test_main_template::type member_hook_t; test::test_generic_set - < member_hook_t - , rebinder + < rebinder >::test_all(); } }; @@ -101,8 +100,7 @@ class test_main_template > testval_traits_t; //nonmember test::test_generic_set - < typename testval_traits_t::nonhook_value_traits - , rebinder + < rebinder >::test_all(); } }; @@ -117,8 +115,7 @@ struct test_main_template_bptr bounded_allocator_scope bounded_scope; (void)bounded_scope; test::test_generic_set - < value_traits - , rebinder< value_traits, ConstantTimeSize, true, Map> + < rebinder< value_traits, ConstantTimeSize, true, Map> >::test_all(); } }; diff --git a/test/sg_multiset_test.cpp b/test/sg_multiset_test.cpp index 5b8dd48..2a71cac 100644 --- a/test/sg_multiset_test.cpp +++ b/test/sg_multiset_test.cpp @@ -22,6 +22,7 @@ template < class ValueTraits, bool FloatingPoint, bool DefaultHolder, bool Map > struct rebinder { typedef tree_rebinder_common common_t; + typedef typename ValueContainer< typename ValueTraits::value_type >::type value_cont_type; template < class Option1 =void , class Option2 =void @@ -61,8 +62,7 @@ class test_main_template //base typedef typename testval_traits_t::base_value_traits base_hook_t; test::test_generic_multiset - < base_hook_t - , rebinder + < rebinder >::test_all(); } }; @@ -77,8 +77,7 @@ class test_main_template //member typedef typename testval_traits_t::member_value_traits member_hook_t; test::test_generic_multiset - < member_hook_t - , rebinder + < rebinder >::test_all(); } }; @@ -92,8 +91,7 @@ class test_main_template > testval_traits_t; //nonmember test::test_generic_multiset - < typename testval_traits_t::nonhook_value_traits - , rebinder + < rebinder >::test_all(); } }; @@ -109,8 +107,7 @@ struct test_main_template_bptr bounded_allocator_scope bounded_scope; (void)bounded_scope; test::test_generic_multiset - < value_traits - , rebinder< value_traits, FloatingPoint, true, Map> + < rebinder< value_traits, FloatingPoint, true, Map> >::test_all(); } }; diff --git a/test/sg_set_test.cpp b/test/sg_set_test.cpp index bd2a2db..a115844 100644 --- a/test/sg_set_test.cpp +++ b/test/sg_set_test.cpp @@ -22,6 +22,7 @@ template < class ValueTraits, bool FloatingPoint, bool DefaultHolder, bool Map > struct rebinder { typedef tree_rebinder_common common_t; + typedef typename ValueContainer< typename ValueTraits::value_type >::type value_cont_type; template < class Option1 =void , class Option2 =void @@ -61,8 +62,7 @@ class test_main_template //base typedef typename testval_traits_t::base_value_traits base_hook_t; test::test_generic_set - < base_hook_t - , rebinder + < rebinder >::test_all(); } }; @@ -77,8 +77,7 @@ class test_main_template //member typedef typename testval_traits_t::member_value_traits member_hook_t; test::test_generic_set - < member_hook_t - , rebinder + < rebinder >::test_all(); } }; @@ -92,8 +91,7 @@ class test_main_template > testval_traits_t; //nonmember test::test_generic_set - < typename testval_traits_t::nonhook_value_traits - , rebinder + < rebinder >::test_all(); } }; @@ -108,8 +106,7 @@ struct test_main_template_bptr bounded_allocator_scope bounded_scope; (void)bounded_scope; test::test_generic_set - < value_traits - , rebinder< value_traits, FloatingPoint, true, Map> + < rebinder< value_traits, FloatingPoint, true, Map> >::test_all(); } }; diff --git a/test/splay_multiset_test.cpp b/test/splay_multiset_test.cpp index ed6bf8c..70fb891 100644 --- a/test/splay_multiset_test.cpp +++ b/test/splay_multiset_test.cpp @@ -22,6 +22,7 @@ template < class ValueTraits, bool ConstantTimeSize, bool DefaultHolder, bool Ma struct rebinder { typedef tree_rebinder_common common_t; + typedef typename ValueContainer< typename ValueTraits::value_type >::type value_cont_type; template < class Option1 =void , class Option2 =void @@ -65,8 +66,7 @@ class test_main_template::type base_hook_t; test::test_generic_multiset - < base_hook_t - , rebinder + < rebinder >::test_all(); } }; @@ -85,8 +85,7 @@ class test_main_template::type member_hook_t; test::test_generic_multiset - < member_hook_t - , rebinder + < rebinder >::test_all(); } }; @@ -100,8 +99,7 @@ class test_main_template > testval_traits_t; //nonmember test::test_generic_multiset - < typename testval_traits_t::nonhook_value_traits - , rebinder + < rebinder >::test_all(); } }; @@ -116,8 +114,7 @@ struct test_main_template_bptr bounded_allocator_scope bounded_scope; (void)bounded_scope; test::test_generic_multiset - < value_traits - , rebinder< value_traits, ConstantTimeSize, true, Map> + < rebinder< value_traits, ConstantTimeSize, true, Map> >::test_all(); } }; diff --git a/test/splay_set_test.cpp b/test/splay_set_test.cpp index eea704f..7aa73b2 100644 --- a/test/splay_set_test.cpp +++ b/test/splay_set_test.cpp @@ -22,6 +22,7 @@ template < class ValueTraits, bool ConstantTimeSize, bool DefaultHolder, bool Ma struct rebinder { typedef tree_rebinder_common common_t; + typedef typename ValueContainer< typename ValueTraits::value_type >::type value_cont_type; template < class Option1 =void , class Option2 =void @@ -65,8 +66,7 @@ class test_main_template::type base_hook_t; test::test_generic_set - < base_hook_t - , rebinder + < rebinder >::test_all(); } }; @@ -85,8 +85,7 @@ class test_main_template::type member_hook_t; test::test_generic_set - < member_hook_t - , rebinder + < rebinder >::test_all(); } }; @@ -100,8 +99,7 @@ class test_main_template > testval_traits_t; //nonmember test::test_generic_set - < typename testval_traits_t::nonhook_value_traits - , rebinder + < rebinder >::test_all(); } }; @@ -116,8 +114,7 @@ struct test_main_template_bptr bounded_allocator_scope bounded_scope; (void)bounded_scope; test::test_generic_set - < value_traits - , rebinder< value_traits, ConstantTimeSize, true, Map> + < rebinder< value_traits, ConstantTimeSize, true, Map> >::test_all(); } }; diff --git a/test/treap_multiset_test.cpp b/test/treap_multiset_test.cpp index c0320f6..923ecd0 100644 --- a/test/treap_multiset_test.cpp +++ b/test/treap_multiset_test.cpp @@ -22,6 +22,7 @@ template < class ValueTraits, bool ConstantTimeSize, bool DefaultHolder, bool Ma struct rebinder { typedef tree_rebinder_common common_t; + typedef typename ValueContainer< typename ValueTraits::value_type >::type value_cont_type; template < class Option1 =void , class Option2 =void @@ -65,8 +66,7 @@ class test_main_template::type base_hook_t; test::test_generic_multiset - < base_hook_t - , rebinder + < rebinder >::test_all(); } }; @@ -85,8 +85,7 @@ class test_main_template::type member_hook_t; test::test_generic_multiset - < member_hook_t - , rebinder + < rebinder >::test_all(); } }; @@ -100,8 +99,7 @@ class test_main_template > testval_traits_t; //nonmember test::test_generic_multiset - < typename testval_traits_t::nonhook_value_traits - , rebinder + < rebinder >::test_all(); } }; @@ -116,8 +114,7 @@ struct test_main_template_bptr bounded_allocator_scope bounded_scope; (void)bounded_scope; test::test_generic_multiset - < value_traits - , rebinder< value_traits, ConstantTimeSize, true, Map> + < rebinder< value_traits, ConstantTimeSize, true, Map> >::test_all(); } }; diff --git a/test/treap_set_test.cpp b/test/treap_set_test.cpp index e54e640..471d5eb 100644 --- a/test/treap_set_test.cpp +++ b/test/treap_set_test.cpp @@ -22,6 +22,7 @@ template < class ValueTraits, bool ConstantTimeSize, bool DefaultHolder, bool Ma struct rebinder { typedef tree_rebinder_common common_t; + typedef typename ValueContainer< typename ValueTraits::value_type >::type value_cont_type; template < class Option1 =void , class Option2 =void @@ -65,8 +66,7 @@ class test_main_template::type base_hook_t; test::test_generic_set - < base_hook_t - , rebinder + < rebinder >::test_all(); } }; @@ -85,8 +85,7 @@ class test_main_template::type member_hook_t; test::test_generic_set - < member_hook_t - , rebinder + < rebinder >::test_all(); } }; @@ -100,8 +99,7 @@ class test_main_template > testval_traits_t; //nonmember test::test_generic_set - < typename testval_traits_t::nonhook_value_traits - , rebinder + < rebinder >::test_all(); } }; @@ -116,8 +114,7 @@ struct test_main_template_bptr bounded_allocator_scope bounded_scope; (void)bounded_scope; test::test_generic_set - < value_traits - , rebinder< value_traits, ConstantTimeSize, true, Map> + < rebinder< value_traits, ConstantTimeSize, true, Map> >::test_all(); } }; diff --git a/test/unordered_multiset_test.cpp b/test/unordered_multiset_test.cpp index 8c0f250..af872b3 100644 --- a/test/unordered_multiset_test.cpp +++ b/test/unordered_multiset_test.cpp @@ -31,6 +31,7 @@ template < class ValueTraits, bool ConstantTimeSize, bool CacheBegin, bool Compa struct rebinder { typedef unordered_rebinder_common common_t; + typedef typename ValueContainer< typename ValueTraits::value_type >::type value_cont_type; template < class Option1 =void , class Option2 =void @@ -85,8 +86,8 @@ class test_main_template >::type base_hook_t; test::test_unordered - < base_hook_t //cache_begin, compare_hash, incremental - , rebinder + < //cache_begin, compare_hash, incremental + rebinder >::test_all(data); } }; @@ -112,8 +113,8 @@ class test_main_template, optimize_multikey >::type member_hook_t; test::test_unordered - < member_hook_t //cache_begin, compare_hash, incremental - , rebinder + < //cache_begin, compare_hash, incremental + rebinder >::test_all(data); } }; @@ -135,8 +136,8 @@ class test_main_template > testval_traits_t; //nonmember test::test_unordered - < typename testval_traits_t::nonhook_value_traits //cache_begin, compare_hash, incremental - , rebinder + < //cache_begin, compare_hash, incremental + rebinder >::test_all(data); } }; diff --git a/test/unordered_set_test.cpp b/test/unordered_set_test.cpp index 6bcfc1d..59a7b70 100644 --- a/test/unordered_set_test.cpp +++ b/test/unordered_set_test.cpp @@ -29,6 +29,7 @@ template < class ValueTraits, bool ConstantTimeSize, bool CacheBegin, bool Compa struct rebinder { typedef unordered_rebinder_common common_t; + typedef typename ValueContainer< typename ValueTraits::value_type >::type value_cont_type; template < class Option1 =void , class Option2 =void @@ -83,8 +84,8 @@ class test_main_template >::type base_hook_t; test::test_unordered - < base_hook_t //cache_begin, compare_hash, incremental - , rebinder + < //cache_begin, compare_hash, incremental + rebinder >::test_all(data); } }; @@ -110,8 +111,8 @@ class test_main_template, optimize_multikey >::type member_hook_t; test::test_unordered - < member_hook_t //cache_begin, compare_hash, incremental - , rebinder + < //cache_begin, compare_hash, incremental + rebinder >::test_all(data); } }; @@ -133,8 +134,8 @@ class test_main_template > testval_traits_t; //nonmember test::test_unordered - < typename testval_traits_t::nonhook_value_traits //cache_begin, compare_hash, incremental - , rebinder + < //cache_begin, compare_hash, incremental + rebinder >::test_all(data); } }; diff --git a/test/unordered_test.hpp b/test/unordered_test.hpp index de743a4..64d8bdf 100644 --- a/test/unordered_test.hpp +++ b/test/unordered_test.hpp @@ -27,16 +27,10 @@ namespace test{ static const std::size_t BucketSize = 8; -template +template struct test_unordered { - typedef typename ValueTraits::value_type value_type; - typedef typename ValueTraits::pointer pointer; - typedef typename ValueTraits::const_pointer const_pointer; - typedef typename ValueContainer< value_type >::type value_cont_type; - typedef typename pointer_traits::reference reference; - typedef typename pointer_traits - ::reference const_reference; + typedef typename ContainerDefiner::value_cont_type value_cont_type; static void test_all(value_cont_type& values); private: @@ -51,9 +45,8 @@ struct test_unordered static void test_clone(value_cont_type& values); }; -template -void test_unordered:: - test_all (value_cont_type& values) +template +void test_unordered::test_all (value_cont_type& values) { typedef typename ContainerDefiner::template container <>::type unordered_type; @@ -98,9 +91,8 @@ void test_unordered:: } //test case due to an error in tree implementation: -template -void test_unordered - ::test_impl() +template +void test_unordered::test_impl() { typedef typename ContainerDefiner::template container <>::type unordered_type; @@ -127,9 +119,8 @@ void test_unordered } //test: constructor, iterator, clear, reverse_iterator, front, back, size: -template -void test_unordered - ::test_sort(value_cont_type& values) +template +void test_unordered::test_sort(value_cont_type& values) { typedef typename ContainerDefiner::template container <>::type unordered_type; @@ -154,9 +145,8 @@ void test_unordered } //test: insert, const_iterator, const_reverse_iterator, erase, iterator_to: -template -void test_unordered - ::test_insert(value_cont_type& values, detail::false_) //not multikey +template +void test_unordered::test_insert(value_cont_type& values, detail::false_) //not multikey { typedef typename ContainerDefiner::template container @@ -212,9 +202,8 @@ void test_unordered } } -template -void test_unordered - ::test_insert(value_cont_type& values, detail::true_) //is multikey +template +void test_unordered::test_insert(value_cont_type& values, detail::true_) //is multikey { typedef typename ContainerDefiner::template container <>::type unordered_type; @@ -405,9 +394,8 @@ void test_unordered } //test: insert (seq-version), swap, erase (seq-version), size: -template -void test_unordered:: - test_swap(value_cont_type& values) +template +void test_unordered::test_swap(value_cont_type& values) { typedef typename ContainerDefiner::template container <>::type unordered_type; @@ -454,9 +442,8 @@ void test_unordered:: //test: rehash: -template -void test_unordered - ::test_rehash(value_cont_type& values, detail::true_) +template +void test_unordered::test_rehash(value_cont_type& values, detail::true_) { typedef typename ContainerDefiner::template container <>::type unordered_type; @@ -583,9 +570,8 @@ void test_unordered { int init_values [] = { 4, 5, 1, 2, 2, 3 }; TEST_INTRUSIVE_SEQUENCE_MAYBEUNIQUE( init_values, testset1 ); } } -template -void test_unordered - ::test_rehash(value_cont_type& values, detail::false_) +template +void test_unordered::test_rehash(value_cont_type& values, detail::false_) { typedef typename ContainerDefiner::template container <>::type unordered_type; @@ -635,12 +621,12 @@ void test_unordered } //test: find, equal_range (lower_bound, upper_bound): -template -void test_unordered:: - test_find(value_cont_type& values) +template +void test_unordered::test_find(value_cont_type& values) { typedef typename ContainerDefiner::template container <>::type unordered_type; + typedef typename unordered_type::value_type value_type; typedef typename unordered_type::bucket_traits bucket_traits; typedef typename unordered_type::key_of_value key_of_value; @@ -673,13 +659,13 @@ void test_unordered:: } -template -void test_unordered - ::test_clone(value_cont_type& values) +template +void test_unordered::test_clone(value_cont_type& values) { typedef typename ContainerDefiner::template container <>::type unordered_type; - typedef std::multiset std_multiset_t; + typedef typename unordered_type::value_type value_type; + typedef std::multiset std_multiset_t; typedef typename unordered_type::bucket_traits bucket_traits; {