diff --git a/doc/intrusive.qbk b/doc/intrusive.qbk index e3c1106..6f11a23 100644 --- a/doc/intrusive.qbk +++ b/doc/intrusive.qbk @@ -3835,12 +3835,6 @@ 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: @@ -3850,6 +3844,9 @@ to be inserted in intrusive containers are allocated using `std::vector` or `std * [@https://svn.boost.org/trac/boost/ticket/12190 Boost Trac #12190: ['Intrusive List + Flat Map combination crashes]] * [@https://svn.boost.org/trac/boost/ticket/12229 Boost Trac #12229: ['intrusive::unordered_set::rehash() broken]] * [@https://svn.boost.org/trac/boost/ticket/12245 Boost Trac #12245: ['bstree uses a shared static size_traits for constant_time_size]] + * [@https://svn.boost.org/trac/boost/ticket/12432 Boost Trac #12432: ['Forced KeyOfValue creation when using custom compare on insert_check]] + +* Implemented `merge` functions in ordered associative containers. [endsect] diff --git a/include/boost/intrusive/bstree.hpp b/include/boost/intrusive/bstree.hpp index e2007e1..4335d76 100644 --- a/include/boost/intrusive/bstree.hpp +++ b/include/boost/intrusive/bstree.hpp @@ -252,17 +252,18 @@ struct get_key_of_value typedef ::boost::intrusive::detail::identity type; }; -template +template struct bst_key_types { + typedef typename pointer_element::type value_type; typedef typename get_key_of_value - < VoidOrKeyOfValue, T>::type key_of_value; - typedef typename key_of_value::type key_type; + < VoidOrKeyOfValue, value_type>::type key_of_value; + typedef typename key_of_value::type key_type; typedef typename get_compare< VoidOrKeyComp , key_type - >::type key_compare; + >::type key_compare; typedef tree_value_compare - value_compare; + value_compare; }; template @@ -271,15 +272,16 @@ struct bstbase2 //Use public inheritance to avoid MSVC bugs with closures : public detail::ebo_functor_holder < typename bst_key_types - < typename ValueTraits::value_type + < typename ValueTraits::pointer , VoidOrKeyOfValue , VoidOrKeyComp + >::value_compare > , public bstbase3 { typedef bstbase3 treeheader_t; - typedef bst_key_types< typename ValueTraits::value_type + typedef bst_key_types< typename ValueTraits::pointer , VoidOrKeyOfValue , VoidOrKeyComp> key_types; typedef typename treeheader_t::value_traits value_traits; diff --git a/include/boost/intrusive/detail/ebo_functor_holder.hpp b/include/boost/intrusive/detail/ebo_functor_holder.hpp index ef278ed..31b2f81 100644 --- a/include/boost/intrusive/detail/ebo_functor_holder.hpp +++ b/include/boost/intrusive/detail/ebo_functor_holder.hpp @@ -259,7 +259,7 @@ class ebo_functor_holder BOOST_INTRUSIVE_FORCEINLINE ebo_functor_holder& operator=(BOOST_COPY_ASSIGN_REF(ebo_functor_holder) x) { const ebo_functor_holder&r = x; - this->get() = x.get(); + this->get() = r; return *this; } diff --git a/include/boost/intrusive/detail/key_nodeptr_comp.hpp b/include/boost/intrusive/detail/key_nodeptr_comp.hpp index 2feb5ed..9d64f09 100644 --- a/include/boost/intrusive/detail/key_nodeptr_comp.hpp +++ b/include/boost/intrusive/detail/key_nodeptr_comp.hpp @@ -23,12 +23,31 @@ #include #include +#include namespace boost { namespace intrusive { namespace detail { +template < class KeyTypeKeyCompare + , class ValueTraits + , class KeyOfValue + > +struct key_nodeptr_comp_types +{ + typedef ValueTraits value_traits; + typedef typename value_traits::value_type value_type; + typedef typename value_traits::node_ptr node_ptr; + typedef typename value_traits::const_node_ptr const_node_ptr; + typedef typename detail::if_c + < detail::is_same::value + , detail::identity + , KeyOfValue + >::type key_of_value; + typedef tree_value_compare + base_t; +}; //This function object transforms a key comparison type to //a function that can compare nodes or nodes with nodes or keys. @@ -38,18 +57,15 @@ template < class KeyTypeKeyCompare > struct key_nodeptr_comp //Use public inheritance to avoid MSVC bugs with closures - : public ebo_functor_holder + : public key_nodeptr_comp_types::base_t { - typedef ValueTraits value_traits; - typedef typename value_traits::value_type value_type; - typedef typename value_traits::node_ptr node_ptr; - typedef typename value_traits::const_node_ptr const_node_ptr; - typedef ebo_functor_holder base_t; - typedef typename detail::if_c - < detail::is_same::value - , detail::identity - , KeyOfValue - >::type key_of_value; + typedef key_nodeptr_comp_types types_t; + typedef typename types_t::value_traits value_traits; + typedef typename types_t::value_type value_type; + typedef typename types_t::node_ptr node_ptr; + typedef typename types_t::const_node_ptr const_node_ptr; + typedef typename types_t::base_t base_t; + typedef typename types_t::key_of_value key_of_value; template struct is_same_or_nodeptr_convertible @@ -58,6 +74,9 @@ struct key_nodeptr_comp static const bool value = same_type || is_convertible::value; }; + base_t base() const + { return static_cast(*this); } + BOOST_INTRUSIVE_FORCEINLINE key_nodeptr_comp(KeyTypeKeyCompare kcomp, const ValueTraits *traits) : base_t(kcomp), traits_(traits) {} @@ -65,48 +84,32 @@ struct key_nodeptr_comp //pred(pnode) template BOOST_INTRUSIVE_FORCEINLINE bool operator()(const T1 &t1, typename enable_if_c< is_same_or_nodeptr_convertible::value >::type* =0) const - { return base_t::get()(key_of_value()(*traits_->to_value_ptr(t1))); } - - template - BOOST_INTRUSIVE_FORCEINLINE bool operator()(const T1 &t1, typename enable_if_c< is_same_or_nodeptr_convertible::value >::type* =0) - { return base_t::get()(key_of_value()(*traits_->to_value_ptr(t1))); } + { return base().get()(key_of_value()(*traits_->to_value_ptr(t1))); } //operator() 2 arg //pred(pnode, pnode) template - BOOST_INTRUSIVE_FORCEINLINE bool operator()(const T1 &t1, const T2 &t2, typename enable_if_c< is_same_or_nodeptr_convertible::value && is_same_or_nodeptr_convertible::value >::type* =0) const - { return base_t::get()(key_of_value()(*traits_->to_value_ptr(t1)), key_of_value()(*traits_->to_value_ptr(t2))); } - - template - BOOST_INTRUSIVE_FORCEINLINE bool operator()(const T1 &t1, const T2 &t2, typename enable_if_c< is_same_or_nodeptr_convertible::value && is_same_or_nodeptr_convertible::value >::type* =0) - { return base_t::get()(key_of_value()(*traits_->to_value_ptr(t1)), key_of_value()(*traits_->to_value_ptr(t2))); } + BOOST_INTRUSIVE_FORCEINLINE bool operator() + (const T1 &t1, const T2 &t2, typename enable_if_c< is_same_or_nodeptr_convertible::value && is_same_or_nodeptr_convertible::value >::type* =0) const + { return base()(*traits_->to_value_ptr(t1), *traits_->to_value_ptr(t2)); } //pred(pnode, key) template - BOOST_INTRUSIVE_FORCEINLINE bool operator()(const T1 &t1, const T2 &t2, typename enable_if_c< is_same_or_nodeptr_convertible::value && !is_same_or_nodeptr_convertible::value >::type* =0) const - { return base_t::get()(key_of_value()(*traits_->to_value_ptr(t1)), t2); } - - template - BOOST_INTRUSIVE_FORCEINLINE bool operator()(const T1 &t1, const T2 &t2, typename enable_if_c< is_same_or_nodeptr_convertible::value && !is_same_or_nodeptr_convertible::value >::type* =0) - { return base_t::get()(key_of_value()(*traits_->to_value_ptr(t1)), t2); } + BOOST_INTRUSIVE_FORCEINLINE bool operator() + (const T1 &t1, const T2 &t2, typename enable_if_c< is_same_or_nodeptr_convertible::value && !is_same_or_nodeptr_convertible::value >::type* =0) const + { return base()(*traits_->to_value_ptr(t1), t2); } //pred(key, pnode) template - BOOST_INTRUSIVE_FORCEINLINE bool operator()(const T1 &t1, const T2 &t2, typename enable_if_c< !is_same_or_nodeptr_convertible::value && is_same_or_nodeptr_convertible::value >::type* =0) const - { return base_t::get()(t1, key_of_value()(*traits_->to_value_ptr(t2))); } - - template - BOOST_INTRUSIVE_FORCEINLINE bool operator()(const T1 &t1, const T2 &t2, typename enable_if_c< !is_same_or_nodeptr_convertible::value && is_same_or_nodeptr_convertible::value >::type* =0) - { return base_t::get()(t1, key_of_value()(*traits_->to_value_ptr(t2))); } + BOOST_INTRUSIVE_FORCEINLINE bool operator() + (const T1 &t1, const T2 &t2, typename enable_if_c< !is_same_or_nodeptr_convertible::value && is_same_or_nodeptr_convertible::value >::type* =0) const + { return base()(t1, *traits_->to_value_ptr(t2)); } //pred(key, key) template - BOOST_INTRUSIVE_FORCEINLINE bool operator()(const T1 &t1, const T2 &t2, typename enable_if_c< !is_same_or_nodeptr_convertible::value && !is_same_or_nodeptr_convertible::value >::type* =0) const - { return base_t::get()(t1, t2); } - - template - BOOST_INTRUSIVE_FORCEINLINE bool operator()(const T1 &t1, const T2 &t2, typename enable_if_c< !is_same_or_nodeptr_convertible::value && !is_same_or_nodeptr_convertible::value >::type* =0) - { return base_t::get()(t1, t2); } + BOOST_INTRUSIVE_FORCEINLINE bool operator() + (const T1 &t1, const T2 &t2, typename enable_if_c< !is_same_or_nodeptr_convertible::value && !is_same_or_nodeptr_convertible::value >::type* =0) const + { return base()(t1, t2); } const ValueTraits *const traits_; }; diff --git a/include/boost/intrusive/detail/tree_value_compare.hpp b/include/boost/intrusive/detail/tree_value_compare.hpp index 70a1d79..c8f596f 100644 --- a/include/boost/intrusive/detail/tree_value_compare.hpp +++ b/include/boost/intrusive/detail/tree_value_compare.hpp @@ -21,19 +21,103 @@ #include #include #include +#include namespace boost{ namespace intrusive{ +//Needed to support smart references to value types +template +struct disable_if_smartref_to + : detail::disable_if_c + < detail::is_same + + ::reference>::value + || detail::is_same + ::type>::type> + ::reference>::value + > +{}; + //This function object takes a KeyCompare function object //and compares values that contains keys using KeyOfValue -template +template< class ValuePtr, class KeyCompare, class KeyOfValue + , bool = boost::intrusive::detail::is_same::type, typename KeyOfValue::type>::value > struct tree_value_compare : public boost::intrusive::detail::ebo_functor_holder { - typedef KeyCompare key_compare; - typedef KeyOfValue key_of_value; - typedef typename KeyOfValue::type key_type; + typedef typename pointer_element::type value_type; + typedef KeyCompare key_compare; + typedef KeyOfValue key_of_value; + typedef typename KeyOfValue::type key_type; + + typedef boost::intrusive::detail::ebo_functor_holder base_t; + + BOOST_INTRUSIVE_FORCEINLINE tree_value_compare() + : base_t() + {} + + BOOST_INTRUSIVE_FORCEINLINE explicit tree_value_compare(const key_compare &kcomp) + : base_t(kcomp) + {} + + BOOST_INTRUSIVE_FORCEINLINE tree_value_compare (const tree_value_compare &x) + : base_t(x.base_t::get()) + {} + + BOOST_INTRUSIVE_FORCEINLINE tree_value_compare &operator=(const tree_value_compare &x) + { this->base_t::get() = x.base_t::get(); return *this; } + + BOOST_INTRUSIVE_FORCEINLINE tree_value_compare &operator=(const key_compare &x) + { this->base_t::get() = x; return *this; } + + BOOST_INTRUSIVE_FORCEINLINE const key_compare &key_comp() const + { return static_cast(*this); } + + BOOST_INTRUSIVE_FORCEINLINE bool operator()(const key_type &key1, const key_type &key2) const + { return this->key_comp()(key1, key2); } + + BOOST_INTRUSIVE_FORCEINLINE bool operator()(const value_type &value1, const value_type &value2) const + { return this->key_comp()(KeyOfValue()(value1), KeyOfValue()(value2)); } + + BOOST_INTRUSIVE_FORCEINLINE bool operator()(const key_type &key1, const value_type &value2) const + { return this->key_comp()(key1, KeyOfValue()(value2)); } + + BOOST_INTRUSIVE_FORCEINLINE bool operator()(const value_type &value1, const key_type &key2) const + { return this->key_comp()(KeyOfValue()(value1), key2); } + + template + BOOST_INTRUSIVE_FORCEINLINE bool operator()( const key_type &key1, const U &nonkey2 + , typename disable_if_smartref_to::type* = 0) const + { return this->key_comp()(key1, nonkey2); } + + template + BOOST_INTRUSIVE_FORCEINLINE bool operator()( const U &nonkey1, const key_type &key2 + , typename disable_if_smartref_to::type* = 0) const + { return this->key_comp()(nonkey1, key2); } + + template + BOOST_INTRUSIVE_FORCEINLINE bool operator()( const value_type &value1, const U &nonvalue2 + , typename disable_if_smartref_to::type* = 0) const + { return this->key_comp()(KeyOfValue()(value1), nonvalue2); } + + template + BOOST_INTRUSIVE_FORCEINLINE bool operator()( const U &nonvalue1, const value_type &value2 + , typename disable_if_smartref_to::type* = 0) const + { return this->key_comp()(nonvalue1, KeyOfValue()(value2)); } +}; + +template +struct tree_value_compare + : public boost::intrusive::detail::ebo_functor_holder +{ + typedef typename pointer_element::type value_type; + typedef KeyCompare key_compare; + typedef KeyOfValue key_of_value; + typedef typename KeyOfValue::type key_type; typedef boost::intrusive::detail::ebo_functor_holder base_t; @@ -59,23 +143,18 @@ struct tree_value_compare BOOST_INTRUSIVE_FORCEINLINE const key_compare &key_comp() const { return static_cast(*this); } - BOOST_INTRUSIVE_FORCEINLINE key_compare &key_comp() - { return static_cast(*this); } - BOOST_INTRUSIVE_FORCEINLINE bool operator()(const key_type &key1, const key_type &key2) const { return this->key_comp()(key1, key2); } template - BOOST_INTRUSIVE_FORCEINLINE bool operator()(const key_type &key1, const U &nonkey2) const - { return this->key_comp()()(key1, KeyOfValue()(nonkey2)); } + BOOST_INTRUSIVE_FORCEINLINE bool operator()( const key_type &key1, const U &nonkey2 + , typename disable_if_smartref_to::type* = 0) const + { return this->key_comp()(key1, nonkey2); } template - BOOST_INTRUSIVE_FORCEINLINE bool operator()(const U &nonkey1, const key_type &key2) const - { return this->key_comp()(KeyOfValue()(nonkey1), key2); } - - template - BOOST_INTRUSIVE_FORCEINLINE bool operator()(const U &nonkey1, const V &nonkey2) const - { return this->key_comp()(KeyOfValue()(nonkey1), KeyOfValue()(nonkey2)); } + BOOST_INTRUSIVE_FORCEINLINE bool operator()(const U &nonkey1, const key_type &key2 + , typename disable_if_smartref_to::type* = 0) const + { return this->key_comp()(nonkey1, key2); } }; } //namespace intrusive{ diff --git a/include/boost/intrusive/priority_compare.hpp b/include/boost/intrusive/priority_compare.hpp index ffade48..f5589ce 100644 --- a/include/boost/intrusive/priority_compare.hpp +++ b/include/boost/intrusive/priority_compare.hpp @@ -26,7 +26,14 @@ namespace boost { namespace intrusive { -template +/// @cond + +template +void priority_order(); + +/// @endcond + +template struct priority_compare { //Compatibility with std::binary_function @@ -40,6 +47,16 @@ struct priority_compare } }; +template <> +struct priority_compare +{ + template + BOOST_INTRUSIVE_FORCEINLINE bool operator()(const T &t, const U &u) const + { + return priority_order(t, u); + } +}; + /// @cond template diff --git a/test/common_functors.hpp b/test/common_functors.hpp index fa76bc8..4e6ac8d 100644 --- a/test/common_functors.hpp +++ b/test/common_functors.hpp @@ -66,6 +66,20 @@ class empty_disposer {} }; +struct any_less +{ + template + bool operator()(const T &t, const U &u) const + { return t < u; } +}; + +struct any_greater +{ + template + bool operator()(const T &t, const U &u) const + { return t > u; } +}; + } //namespace test { } //namespace intrusive { } //namespace boost { diff --git a/test/generic_multiset_test.hpp b/test/generic_multiset_test.hpp index 6caeca2..2a0ee28 100644 --- a/test/generic_multiset_test.hpp +++ b/test/generic_multiset_test.hpp @@ -207,6 +207,7 @@ void test_generic_multiset::test_merge(value_cont_type& values (&cmp_val)->value_ = 2; BOOST_TEST (*testset2.find(key_of_value()(cmp_val)) == values[5]); + BOOST_TEST (*testset2.find(2, any_greater()) == values[5]); BOOST_TEST (&*(++testset2.find(key_of_value()(cmp_val))) == &values[1]); testset1.merge(testset2); @@ -217,6 +218,7 @@ void test_generic_multiset::test_merge(value_cont_type& values { 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(2, any_less()) == values[5]); BOOST_TEST (&*(++testset1.find(key_of_value()(cmp_val))) == &values[1]); BOOST_TEST (testset2.empty()); } @@ -237,9 +239,11 @@ void test_generic_multiset::test_find(value_cont_type& values) 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 == testset.find (2, any_less())); BOOST_TEST (i->value_ == 2); BOOST_TEST ((++i)->value_ == 2); std::pair range = testset.equal_range (key_of_value()(cmp_val)); + BOOST_TEST(range == testset.equal_range (2, any_less())); BOOST_TEST (range.first->value_ == 2); BOOST_TEST (range.second->value_ == 3); @@ -247,6 +251,7 @@ void test_generic_multiset::test_find(value_cont_type& values) (&cmp_val)->value_ = 7; BOOST_TEST (testset.find(key_of_value()(cmp_val)) == testset.end()); + BOOST_TEST (testset.find (7, any_less()) == testset.end()); } { //1, 2, 2, 3, 4, 5 const multiset_type &const_testset = testset; @@ -260,6 +265,7 @@ void test_generic_multiset::test_find(value_cont_type& values) (&cmp_val_upper)->value_ = 2; //left-closed, right-closed range = testset.bounded_range (key_of_value()(cmp_val_lower), key_of_value()(cmp_val_upper), true, true); + BOOST_TEST (range == testset.bounded_range (1, 2, any_less(), true, true)); BOOST_TEST (range.first->value_ == 1); BOOST_TEST (range.second->value_ == 3); BOOST_TEST (boost::intrusive::iterator_distance (range.first, range.second) == 3); @@ -268,6 +274,7 @@ void test_generic_multiset::test_find(value_cont_type& values) (&cmp_val_lower)->value_ = 1; (&cmp_val_upper)->value_ = 2; const_range = const_testset.bounded_range (key_of_value()(cmp_val_lower), key_of_value()(cmp_val_upper), true, false); + BOOST_TEST (const_range == const_testset.bounded_range (1, 2, any_less(), true, false)); BOOST_TEST (const_range.first->value_ == 1); BOOST_TEST (const_range.second->value_ == 2); BOOST_TEST (boost::intrusive::iterator_distance (const_range.first, const_range.second) == 1); @@ -275,6 +282,7 @@ void test_generic_multiset::test_find(value_cont_type& values) (&cmp_val_lower)->value_ = 1; (&cmp_val_upper)->value_ = 3; range = testset.bounded_range (key_of_value()(cmp_val_lower), key_of_value()(cmp_val_upper), true, false); + BOOST_TEST (range == testset.bounded_range (1, 3, any_less(), true, false)); BOOST_TEST (range.first->value_ == 1); BOOST_TEST (range.second->value_ == 3); BOOST_TEST (boost::intrusive::iterator_distance (range.first, range.second) == 3); @@ -283,6 +291,7 @@ void test_generic_multiset::test_find(value_cont_type& values) (&cmp_val_lower)->value_ = 1; (&cmp_val_upper)->value_ = 2; const_range = const_testset.bounded_range (key_of_value()(cmp_val_lower), key_of_value()(cmp_val_upper), false, true); + BOOST_TEST (const_range == const_testset.bounded_range (1, 2, any_less(), false, true)); BOOST_TEST (const_range.first->value_ == 2); BOOST_TEST (const_range.second->value_ == 3); BOOST_TEST (boost::intrusive::iterator_distance (const_range.first, const_range.second) == 2); @@ -291,6 +300,7 @@ void test_generic_multiset::test_find(value_cont_type& values) (&cmp_val_lower)->value_ = 1; (&cmp_val_upper)->value_ = 2; range = testset.bounded_range (key_of_value()(cmp_val_lower), key_of_value()(cmp_val_upper), false, false); + BOOST_TEST (range == testset.bounded_range (1, 2, any_less(), false, false)); BOOST_TEST (range.first->value_ == 2); BOOST_TEST (range.second->value_ == 2); BOOST_TEST (boost::intrusive::iterator_distance (range.first, range.second) == 0); @@ -299,6 +309,7 @@ void test_generic_multiset::test_find(value_cont_type& values) (&cmp_val_lower)->value_ = 5; (&cmp_val_upper)->value_ = 6; const_range = const_testset.bounded_range (key_of_value()(cmp_val_lower), key_of_value()(cmp_val_upper), true, false); + BOOST_TEST (const_range == const_testset.bounded_range (5, 6, any_less(), true, false)); BOOST_TEST (const_range.first->value_ == 5); BOOST_TEST (const_range.second == const_testset.end()); BOOST_TEST (boost::intrusive::iterator_distance (const_range.first, const_range.second) == 1); diff --git a/test/generic_set_test.hpp b/test/generic_set_test.hpp index e3425d1..bb73db8 100644 --- a/test/generic_set_test.hpp +++ b/test/generic_set_test.hpp @@ -197,17 +197,16 @@ void test_generic_set::test_insert_advanced typedef typename ContainerDefiner::template container <>::type set_type; typedef typename set_type::key_of_value key_of_value; - typedef typename set_type::key_type key_type; typedef typename set_type::value_type value_type; - typedef priority_compare prio_comp_t; + typedef priority_compare<> prio_comp_t; { 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)); - BOOST_TEST ((!testset.insert_check(testset.begin(), key_of_value()(v), testset.key_comp(), prio_comp_t(), data).second)); + BOOST_TEST ((!testset.insert_check(1, any_less(), prio_comp_t(), data).second)); + BOOST_TEST ((!testset.insert_check(testset.begin(), 1, any_less(), prio_comp_t(), data).second)); BOOST_TEST ((!testset.insert_check(key_of_value()(v), data).second)); BOOST_TEST ((!testset.insert_check(testset.begin(), key_of_value()(v), data).second)); } @@ -228,9 +227,9 @@ void test_generic_set::test_insert_advanced 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)); - BOOST_TEST ((!testset.insert_check(testset.begin(), key_of_value()(v), testset.key_comp(), data).second)); + BOOST_TEST ((!testset.insert_check(1, any_less(), data).second)); BOOST_TEST ((!testset.insert_check(key_of_value()(v), data).second)); + BOOST_TEST ((!testset.insert_check(testset.begin(), 1, any_less(), data).second)); BOOST_TEST ((!testset.insert_check(testset.begin(), key_of_value()(v), data).second)); } } @@ -319,9 +318,12 @@ void test_generic_set::test_find(value_cont_type& values) reference cmp_val = cmp_val_cont.front(); (&cmp_val)->value_ = 2; iterator i = testset.find(key_of_value()(cmp_val)); + BOOST_TEST (i == testset.find(2, any_less())); BOOST_TEST (i->value_ == 2); BOOST_TEST ((++i)->value_ != 2); + std::pair range = testset.equal_range (key_of_value()(cmp_val)); + BOOST_TEST(range == testset.equal_range (2, any_less())); BOOST_TEST (range.first->value_ == 2); BOOST_TEST (range.second->value_ == 3); @@ -329,6 +331,7 @@ void test_generic_set::test_find(value_cont_type& values) (&cmp_val)->value_ = 7; BOOST_TEST (testset.find (key_of_value()(cmp_val)) == testset.end()); + BOOST_TEST (testset.find (7, any_less()) == testset.end()); } { @@ -344,6 +347,7 @@ void test_generic_set::test_find(value_cont_type& values) (&cmp_val_upper)->value_ = 2; //left-closed, right-closed range = testset.bounded_range (key_of_value()(cmp_val_lower), key_of_value()(cmp_val_upper), true, true); + BOOST_TEST (range == testset.bounded_range (1, 2, any_less(), true, true)); BOOST_TEST (range.first->value_ == 1); BOOST_TEST (range.second->value_ == 3); BOOST_TEST (boost::intrusive::iterator_distance (range.first, range.second) == 2); @@ -352,6 +356,7 @@ void test_generic_set::test_find(value_cont_type& values) (&cmp_val_lower)->value_ = 1; (&cmp_val_upper)->value_ = 2; const_range = const_testset.bounded_range (key_of_value()(cmp_val_lower), key_of_value()(cmp_val_upper), true, false); + BOOST_TEST (const_range == const_testset.bounded_range (1, 2, any_less(), true, false)); BOOST_TEST (const_range.first->value_ == 1); BOOST_TEST (const_range.second->value_ == 2); BOOST_TEST (boost::intrusive::iterator_distance (const_range.first, const_range.second) == 1); @@ -359,6 +364,7 @@ void test_generic_set::test_find(value_cont_type& values) (&cmp_val_lower)->value_ = 1; (&cmp_val_upper)->value_ = 3; range = testset.bounded_range (key_of_value()(cmp_val_lower), key_of_value()(cmp_val_upper), true, false); + BOOST_TEST (range == testset.bounded_range (1, 3, any_less(), true, false)); BOOST_TEST (range.first->value_ == 1); BOOST_TEST (range.second->value_ == 3); BOOST_TEST (boost::intrusive::iterator_distance (range.first, range.second) == 2); @@ -367,6 +373,7 @@ void test_generic_set::test_find(value_cont_type& values) (&cmp_val_lower)->value_ = 1; (&cmp_val_upper)->value_ = 2; const_range = const_testset.bounded_range (key_of_value()(cmp_val_lower), key_of_value()(cmp_val_upper), false, true); + BOOST_TEST (const_range == const_testset.bounded_range (1, 2, any_less(), false, true)); BOOST_TEST (const_range.first->value_ == 2); BOOST_TEST (const_range.second->value_ == 3); BOOST_TEST (boost::intrusive::iterator_distance (const_range.first, const_range.second) == 1); @@ -375,6 +382,7 @@ void test_generic_set::test_find(value_cont_type& values) (&cmp_val_lower)->value_ = 1; (&cmp_val_upper)->value_ = 2; range = testset.bounded_range (key_of_value()(cmp_val_lower), key_of_value()(cmp_val_upper), false, false); + BOOST_TEST (range == testset.bounded_range (1, 2, any_less(), false, false)); BOOST_TEST (range.first->value_ == 2); BOOST_TEST (range.second->value_ == 2); BOOST_TEST (boost::intrusive::iterator_distance (range.first, range.second) == 0); @@ -383,6 +391,7 @@ void test_generic_set::test_find(value_cont_type& values) (&cmp_val_lower)->value_ = 5; (&cmp_val_upper)->value_ = 6; const_range = const_testset.bounded_range (key_of_value()(cmp_val_lower), key_of_value()(cmp_val_upper), true, false); + BOOST_TEST (const_range == const_testset.bounded_range (5, 6, any_less(), true, false)); BOOST_TEST (const_range.first->value_ == 5); BOOST_TEST (const_range.second == const_testset.end()); BOOST_TEST (boost::intrusive::iterator_distance (const_range.first, const_range.second) == 1); diff --git a/test/itestvalue.hpp b/test/itestvalue.hpp index 0f24bbf..1a4ecda 100644 --- a/test/itestvalue.hpp +++ b/test/itestvalue.hpp @@ -136,22 +136,19 @@ struct testvalue } }; +template +std::size_t priority_hash(const T &t) +{ return boost::hash()((&t)->int_value()); } -template -bool priority_order(const Type& t1, const Type& t2) -{ - std::size_t hash1 = boost::hash()((&t1)->int_value()); - boost::hash_combine(hash1, -hash1); - std::size_t hash2 = boost::hash()((&t2)->int_value()); - boost::hash_combine(hash2, -hash2); - return hash1 < hash2; -} +std::size_t priority_hash(int i) +{ return boost::hash()(i); } -bool priority_order(int t1, int t2) +template +bool priority_order(const T& t1, const U& t2) { - std::size_t hash1 = boost::hash()(t1); + std::size_t hash1 = (priority_hash)(t1); boost::hash_combine(hash1, -hash1); - std::size_t hash2 = boost::hash()(t2); + std::size_t hash2 = (priority_hash)(t2); boost::hash_combine(hash2, -hash2); return hash1 < hash2; }