Fixed Trac #12432 ("Forced KeyOfValue creation when using custom compare on insert_check")

This commit is contained in:
Ion Gaztañaga
2016-09-03 00:01:55 +02:00
parent d5b81dc59a
commit 9ac060a6ae
10 changed files with 217 additions and 88 deletions

View File

@@ -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<T>::rehash() broken]]
* [@https://svn.boost.org/trac/boost/ticket/12245 Boost Trac #12245: ['bstree uses a shared static size_traits for constant_time_size<false>]]
* [@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]

View File

@@ -252,17 +252,18 @@ struct get_key_of_value<void, T>
typedef ::boost::intrusive::detail::identity<T> type;
};
template<class T, class VoidOrKeyOfValue, class VoidOrKeyComp>
template<class ValuePtr, class VoidOrKeyOfValue, class VoidOrKeyComp>
struct bst_key_types
{
typedef typename pointer_element<ValuePtr>::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
<key_compare, key_of_value> value_compare;
<ValuePtr, key_compare, key_of_value> value_compare;
};
template<class ValueTraits, class VoidOrKeyOfValue, class VoidOrKeyComp, algo_types AlgoType, typename HeaderHolder>
@@ -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<ValueTraits, AlgoType, HeaderHolder>
{
typedef bstbase3<ValueTraits, AlgoType, HeaderHolder> 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;

View File

@@ -259,7 +259,7 @@ class ebo_functor_holder<T, false>
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;
}

View File

@@ -23,12 +23,31 @@
#include <boost/intrusive/detail/mpl.hpp>
#include <boost/intrusive/detail/ebo_functor_holder.hpp>
#include <boost/intrusive/detail/tree_value_compare.hpp>
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<KeyOfValue, void>::value
, detail::identity<value_type>
, KeyOfValue
>::type key_of_value;
typedef tree_value_compare
<typename ValueTraits::pointer, KeyTypeKeyCompare, key_of_value> 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<KeyTypeKeyCompare>
: public key_nodeptr_comp_types<KeyTypeKeyCompare, ValueTraits, KeyOfValue>::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<KeyTypeKeyCompare> base_t;
typedef typename detail::if_c
< detail::is_same<KeyOfValue, void>::value
, detail::identity<value_type>
, KeyOfValue
>::type key_of_value;
typedef key_nodeptr_comp_types<KeyTypeKeyCompare, ValueTraits, KeyOfValue> 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 <class P1>
struct is_same_or_nodeptr_convertible
@@ -58,6 +74,9 @@ struct key_nodeptr_comp
static const bool value = same_type || is_convertible<P1, const_node_ptr>::value;
};
base_t base() const
{ return static_cast<const base_t&>(*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<class T1>
BOOST_INTRUSIVE_FORCEINLINE bool operator()(const T1 &t1, typename enable_if_c< is_same_or_nodeptr_convertible<T1>::value >::type* =0) const
{ return base_t::get()(key_of_value()(*traits_->to_value_ptr(t1))); }
template<class T1>
BOOST_INTRUSIVE_FORCEINLINE bool operator()(const T1 &t1, typename enable_if_c< is_same_or_nodeptr_convertible<T1>::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<class T1, class T2>
BOOST_INTRUSIVE_FORCEINLINE bool operator()(const T1 &t1, const T2 &t2, typename enable_if_c< is_same_or_nodeptr_convertible<T1>::value && is_same_or_nodeptr_convertible<T2>::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<class T1, class T2>
BOOST_INTRUSIVE_FORCEINLINE bool operator()(const T1 &t1, const T2 &t2, typename enable_if_c< is_same_or_nodeptr_convertible<T1>::value && is_same_or_nodeptr_convertible<T2>::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<T1>::value && is_same_or_nodeptr_convertible<T2>::value >::type* =0) const
{ return base()(*traits_->to_value_ptr(t1), *traits_->to_value_ptr(t2)); }
//pred(pnode, key)
template<class T1, class T2>
BOOST_INTRUSIVE_FORCEINLINE bool operator()(const T1 &t1, const T2 &t2, typename enable_if_c< is_same_or_nodeptr_convertible<T1>::value && !is_same_or_nodeptr_convertible<T2>::value >::type* =0) const
{ return base_t::get()(key_of_value()(*traits_->to_value_ptr(t1)), t2); }
template<class T1, class T2>
BOOST_INTRUSIVE_FORCEINLINE bool operator()(const T1 &t1, const T2 &t2, typename enable_if_c< is_same_or_nodeptr_convertible<T1>::value && !is_same_or_nodeptr_convertible<T2>::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<T1>::value && !is_same_or_nodeptr_convertible<T2>::value >::type* =0) const
{ return base()(*traits_->to_value_ptr(t1), t2); }
//pred(key, pnode)
template<class T1, class T2>
BOOST_INTRUSIVE_FORCEINLINE bool operator()(const T1 &t1, const T2 &t2, typename enable_if_c< !is_same_or_nodeptr_convertible<T1>::value && is_same_or_nodeptr_convertible<T2>::value >::type* =0) const
{ return base_t::get()(t1, key_of_value()(*traits_->to_value_ptr(t2))); }
template<class T1, class T2>
BOOST_INTRUSIVE_FORCEINLINE bool operator()(const T1 &t1, const T2 &t2, typename enable_if_c< !is_same_or_nodeptr_convertible<T1>::value && is_same_or_nodeptr_convertible<T2>::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<T1>::value && is_same_or_nodeptr_convertible<T2>::value >::type* =0) const
{ return base()(t1, *traits_->to_value_ptr(t2)); }
//pred(key, key)
template<class T1, class T2>
BOOST_INTRUSIVE_FORCEINLINE bool operator()(const T1 &t1, const T2 &t2, typename enable_if_c< !is_same_or_nodeptr_convertible<T1>::value && !is_same_or_nodeptr_convertible<T2>::value >::type* =0) const
{ return base_t::get()(t1, t2); }
template<class T1, class T2>
BOOST_INTRUSIVE_FORCEINLINE bool operator()(const T1 &t1, const T2 &t2, typename enable_if_c< !is_same_or_nodeptr_convertible<T1>::value && !is_same_or_nodeptr_convertible<T2>::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<T1>::value && !is_same_or_nodeptr_convertible<T2>::value >::type* =0) const
{ return base()(t1, t2); }
const ValueTraits *const traits_;
};

View File

@@ -21,19 +21,103 @@
#include <boost/intrusive/detail/workaround.hpp>
#include <boost/intrusive/detail/mpl.hpp>
#include <boost/intrusive/detail/ebo_functor_holder.hpp>
#include <boost/intrusive/pointer_traits.hpp>
namespace boost{
namespace intrusive{
//Needed to support smart references to value types
template <class From, class ValuePtr>
struct disable_if_smartref_to
: detail::disable_if_c
< detail::is_same
<From, typename pointer_traits
<ValuePtr>
::reference>::value
|| detail::is_same
<From, typename pointer_traits
< typename pointer_rebind
<ValuePtr, const typename pointer_element<ValuePtr>::type>::type>
::reference>::value
>
{};
//This function object takes a KeyCompare function object
//and compares values that contains keys using KeyOfValue
template<class KeyCompare, class KeyOfValue>
template< class ValuePtr, class KeyCompare, class KeyOfValue
, bool = boost::intrusive::detail::is_same<typename pointer_element<ValuePtr>::type, typename KeyOfValue::type>::value >
struct tree_value_compare
: public boost::intrusive::detail::ebo_functor_holder<KeyCompare>
{
typedef KeyCompare key_compare;
typedef KeyOfValue key_of_value;
typedef typename KeyOfValue::type key_type;
typedef typename pointer_element<ValuePtr>::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<KeyCompare> 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<const key_compare &>(*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<class U>
BOOST_INTRUSIVE_FORCEINLINE bool operator()( const key_type &key1, const U &nonkey2
, typename disable_if_smartref_to<U, ValuePtr>::type* = 0) const
{ return this->key_comp()(key1, nonkey2); }
template<class U>
BOOST_INTRUSIVE_FORCEINLINE bool operator()( const U &nonkey1, const key_type &key2
, typename disable_if_smartref_to<U, ValuePtr>::type* = 0) const
{ return this->key_comp()(nonkey1, key2); }
template<class U>
BOOST_INTRUSIVE_FORCEINLINE bool operator()( const value_type &value1, const U &nonvalue2
, typename disable_if_smartref_to<U, ValuePtr>::type* = 0) const
{ return this->key_comp()(KeyOfValue()(value1), nonvalue2); }
template<class U>
BOOST_INTRUSIVE_FORCEINLINE bool operator()( const U &nonvalue1, const value_type &value2
, typename disable_if_smartref_to<U, ValuePtr>::type* = 0) const
{ return this->key_comp()(nonvalue1, KeyOfValue()(value2)); }
};
template<class ValuePtr, class KeyCompare, class KeyOfValue>
struct tree_value_compare<ValuePtr, KeyCompare, KeyOfValue, true>
: public boost::intrusive::detail::ebo_functor_holder<KeyCompare>
{
typedef typename pointer_element<ValuePtr>::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<KeyCompare> base_t;
@@ -59,23 +143,18 @@ struct tree_value_compare
BOOST_INTRUSIVE_FORCEINLINE const key_compare &key_comp() const
{ return static_cast<const key_compare &>(*this); }
BOOST_INTRUSIVE_FORCEINLINE key_compare &key_comp()
{ return static_cast<key_compare &>(*this); }
BOOST_INTRUSIVE_FORCEINLINE bool operator()(const key_type &key1, const key_type &key2) const
{ return this->key_comp()(key1, key2); }
template<class U>
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<U, ValuePtr>::type* = 0) const
{ return this->key_comp()(key1, nonkey2); }
template<class U>
BOOST_INTRUSIVE_FORCEINLINE bool operator()(const U &nonkey1, const key_type &key2) const
{ return this->key_comp()(KeyOfValue()(nonkey1), key2); }
template<class U, class V>
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<U, ValuePtr>::type* = 0) const
{ return this->key_comp()(nonkey1, key2); }
};
} //namespace intrusive{

View File

@@ -26,7 +26,14 @@
namespace boost {
namespace intrusive {
template <class T>
/// @cond
template<class U>
void priority_order();
/// @endcond
template <class T = void>
struct priority_compare
{
//Compatibility with std::binary_function
@@ -40,6 +47,16 @@ struct priority_compare
}
};
template <>
struct priority_compare<void>
{
template<class T, class U>
BOOST_INTRUSIVE_FORCEINLINE bool operator()(const T &t, const U &u) const
{
return priority_order(t, u);
}
};
/// @cond
template<class PrioComp, class T>

View File

@@ -66,6 +66,20 @@ class empty_disposer
{}
};
struct any_less
{
template<class T, class U>
bool operator()(const T &t, const U &u) const
{ return t < u; }
};
struct any_greater
{
template<class T, class U>
bool operator()(const T &t, const U &u) const
{ return t > u; }
};
} //namespace test {
} //namespace intrusive {
} //namespace boost {

View File

@@ -207,6 +207,7 @@ void test_generic_multiset<ContainerDefiner>::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<ContainerDefiner>::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<ContainerDefiner>::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<iterator,iterator> 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<ContainerDefiner>::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<ContainerDefiner>::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<ContainerDefiner>::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<ContainerDefiner>::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<ContainerDefiner>::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<ContainerDefiner>::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<ContainerDefiner>::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);

View File

@@ -197,17 +197,16 @@ void test_generic_set<ContainerDefiner>::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<key_type> 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<ContainerDefiner>::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<ContainerDefiner>::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<iterator,iterator> 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<ContainerDefiner>::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<ContainerDefiner>::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<ContainerDefiner>::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<ContainerDefiner>::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<ContainerDefiner>::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<ContainerDefiner>::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<ContainerDefiner>::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);

View File

@@ -136,22 +136,19 @@ struct testvalue
}
};
template<class T>
std::size_t priority_hash(const T &t)
{ return boost::hash<int>()((&t)->int_value()); }
template <class Type>
bool priority_order(const Type& t1, const Type& t2)
{
std::size_t hash1 = boost::hash<int>()((&t1)->int_value());
boost::hash_combine(hash1, -hash1);
std::size_t hash2 = boost::hash<int>()((&t2)->int_value());
boost::hash_combine(hash2, -hash2);
return hash1 < hash2;
}
std::size_t priority_hash(int i)
{ return boost::hash<int>()(i); }
bool priority_order(int t1, int t2)
template <class T, class U>
bool priority_order(const T& t1, const U& t2)
{
std::size_t hash1 = boost::hash<int>()(t1);
std::size_t hash1 = (priority_hash)(t1);
boost::hash_combine(hash1, -hash1);
std::size_t hash2 = boost::hash<int>()(t2);
std::size_t hash2 = (priority_hash)(t2);
boost::hash_combine(hash2, -hash2);
return hash1 < hash2;
}