forked from boostorg/intrusive
Fixed Trac #12432 ("Forced KeyOfValue creation when using custom compare on insert_check")
This commit is contained in:
1 parent
d5b81dc59a
commit
9ac060a6ae
10 files changed
+217
-88
No files matched your search
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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_;
|
||||
};
|
||||
|
||||
@@ -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{
|
||||
|
||||
@@ -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>
|
||||
|
||||
Reference in new issue
Block a user