forked from boostorg/intrusive
Merge branch 'fix_voidptr_keys' of https://github.com/Lastique/intrusive into Lastique-fix_voidptr_keys
This commit is contained in:
@@ -147,7 +147,7 @@ BOOST_INTRUSIVE_FORCEINLINE typename iterator_enable_if_tag<InputIt, std::input_
|
||||
iterator_advance(InputIt& it, Distance n)
|
||||
{
|
||||
while(n--)
|
||||
++it;
|
||||
++it;
|
||||
}
|
||||
|
||||
template<class InputIt, class Distance>
|
||||
@@ -155,7 +155,7 @@ typename iterator_enable_if_tag<InputIt, std::forward_iterator_tag>::type
|
||||
iterator_advance(InputIt& it, Distance n)
|
||||
{
|
||||
while(n--)
|
||||
++it;
|
||||
++it;
|
||||
}
|
||||
|
||||
template<class InputIt, class Distance>
|
||||
@@ -163,9 +163,9 @@ BOOST_INTRUSIVE_FORCEINLINE typename iterator_enable_if_tag<InputIt, std::bidire
|
||||
iterator_advance(InputIt& it, Distance n)
|
||||
{
|
||||
for (; 0 < n; --n)
|
||||
++it;
|
||||
++it;
|
||||
for (; n < 0; ++n)
|
||||
--it;
|
||||
--it;
|
||||
}
|
||||
|
||||
template<class InputIt, class Distance>
|
||||
@@ -181,7 +181,7 @@ BOOST_INTRUSIVE_FORCEINLINE typename iterator_enable_if_convertible_tag
|
||||
iterator_advance(InputIt& it, Distance n)
|
||||
{
|
||||
while(n--)
|
||||
++it;
|
||||
++it;
|
||||
}
|
||||
|
||||
template<class InputIt, class Distance>
|
||||
@@ -190,7 +190,7 @@ BOOST_INTRUSIVE_FORCEINLINE typename iterator_enable_if_convertible_tag
|
||||
iterator_advance(InputIt& it, Distance n)
|
||||
{
|
||||
while(n--)
|
||||
++it;
|
||||
++it;
|
||||
}
|
||||
|
||||
template<class InputIt, class Distance>
|
||||
@@ -199,7 +199,7 @@ BOOST_INTRUSIVE_FORCEINLINE typename iterator_enable_if_convertible_tag
|
||||
iterator_advance(InputIt& it, Distance n)
|
||||
{
|
||||
while(n--)
|
||||
++it;
|
||||
++it;
|
||||
}
|
||||
|
||||
template<class InputIt, class Distance>
|
||||
@@ -208,9 +208,9 @@ BOOST_INTRUSIVE_FORCEINLINE typename iterator_enable_if_convertible_tag
|
||||
iterator_advance(InputIt& it, Distance n)
|
||||
{
|
||||
for (; 0 < n; --n)
|
||||
++it;
|
||||
++it;
|
||||
for (; n < 0; ++n)
|
||||
--it;
|
||||
--it;
|
||||
}
|
||||
|
||||
class fake{};
|
||||
@@ -233,7 +233,7 @@ typename iterator_disable_if_tag_difference_type
|
||||
{
|
||||
typename iterator_traits<InputIt>::difference_type off = 0;
|
||||
while(first != last){
|
||||
++off;
|
||||
++off;
|
||||
++first;
|
||||
}
|
||||
return off;
|
||||
|
@@ -27,7 +27,7 @@ namespace boost{
|
||||
namespace intrusive{
|
||||
|
||||
//Needed to support smart references to value types
|
||||
template <class From, class ValuePtr>
|
||||
template <class From, class ValuePtr, class R = void>
|
||||
struct disable_if_smartref_to
|
||||
: detail::disable_if_c
|
||||
< detail::is_same
|
||||
@@ -39,7 +39,8 @@ struct disable_if_smartref_to
|
||||
< typename pointer_rebind
|
||||
< ValuePtr
|
||||
, const typename boost::movelib::pointer_element<ValuePtr>::type>::type>
|
||||
::reference>::value
|
||||
::reference>::value,
|
||||
R
|
||||
>
|
||||
{};
|
||||
|
||||
@@ -51,6 +52,10 @@ template< class ValuePtr, class KeyCompare, class KeyOfValue, class Ret = bool
|
||||
struct tree_value_compare
|
||||
: public boost::intrusive::detail::ebo_functor_holder<KeyCompare>
|
||||
{
|
||||
private:
|
||||
struct sfinae_type;
|
||||
|
||||
public:
|
||||
typedef typename
|
||||
boost::movelib::pointer_element<ValuePtr>::type value_type;
|
||||
typedef KeyCompare key_compare;
|
||||
@@ -88,7 +93,7 @@ struct tree_value_compare
|
||||
|
||||
template<class U>
|
||||
BOOST_INTRUSIVE_FORCEINLINE Ret operator()( const U &nonkey
|
||||
, typename disable_if_smartref_to<U, ValuePtr>::type* = 0) const
|
||||
, typename disable_if_smartref_to<U, ValuePtr, sfinae_type*>::type = 0) const
|
||||
{ return this->key_comp()(nonkey); }
|
||||
|
||||
BOOST_INTRUSIVE_FORCEINLINE Ret operator()(const key_type &key1, const key_type &key2) const
|
||||
@@ -105,22 +110,22 @@ struct tree_value_compare
|
||||
|
||||
template<class U>
|
||||
BOOST_INTRUSIVE_FORCEINLINE Ret operator()( const key_type &key1, const U &nonkey2
|
||||
, typename disable_if_smartref_to<U, ValuePtr>::type* = 0) const
|
||||
, typename disable_if_smartref_to<U, ValuePtr, sfinae_type*>::type = 0) const
|
||||
{ return this->key_comp()(key1, nonkey2); }
|
||||
|
||||
template<class U>
|
||||
BOOST_INTRUSIVE_FORCEINLINE Ret operator()( const U &nonkey1, const key_type &key2
|
||||
, typename disable_if_smartref_to<U, ValuePtr>::type* = 0) const
|
||||
, typename disable_if_smartref_to<U, ValuePtr, sfinae_type*>::type = 0) const
|
||||
{ return this->key_comp()(nonkey1, key2); }
|
||||
|
||||
template<class U>
|
||||
BOOST_INTRUSIVE_FORCEINLINE Ret operator()( const value_type &value1, const U &nonvalue2
|
||||
, typename disable_if_smartref_to<U, ValuePtr>::type* = 0) const
|
||||
, typename disable_if_smartref_to<U, ValuePtr, sfinae_type*>::type = 0) const
|
||||
{ return this->key_comp()(KeyOfValue()(value1), nonvalue2); }
|
||||
|
||||
template<class U>
|
||||
BOOST_INTRUSIVE_FORCEINLINE Ret operator()( const U &nonvalue1, const value_type &value2
|
||||
, typename disable_if_smartref_to<U, ValuePtr>::type* = 0) const
|
||||
, typename disable_if_smartref_to<U, ValuePtr, sfinae_type*>::type = 0) const
|
||||
{ return this->key_comp()(nonvalue1, KeyOfValue()(value2)); }
|
||||
};
|
||||
|
||||
@@ -128,6 +133,10 @@ template<class ValuePtr, class KeyCompare, class KeyOfValue, class Ret>
|
||||
struct tree_value_compare<ValuePtr, KeyCompare, KeyOfValue, Ret, true>
|
||||
: public boost::intrusive::detail::ebo_functor_holder<KeyCompare>
|
||||
{
|
||||
private:
|
||||
struct sfinae_type;
|
||||
|
||||
public:
|
||||
typedef typename
|
||||
boost::movelib::pointer_element<ValuePtr>::type value_type;
|
||||
typedef KeyCompare key_compare;
|
||||
@@ -163,7 +172,7 @@ struct tree_value_compare<ValuePtr, KeyCompare, KeyOfValue, Ret, true>
|
||||
|
||||
template<class U>
|
||||
BOOST_INTRUSIVE_FORCEINLINE Ret operator()( const U &nonkey
|
||||
, typename disable_if_smartref_to<U, ValuePtr>::type* = 0) const
|
||||
, typename disable_if_smartref_to<U, ValuePtr, sfinae_type*>::type = 0) const
|
||||
{ return this->key_comp()(nonkey); }
|
||||
|
||||
BOOST_INTRUSIVE_FORCEINLINE Ret operator()(const key_type &key1, const key_type &key2) const
|
||||
@@ -171,12 +180,12 @@ struct tree_value_compare<ValuePtr, KeyCompare, KeyOfValue, Ret, true>
|
||||
|
||||
template<class U>
|
||||
BOOST_INTRUSIVE_FORCEINLINE Ret operator()( const key_type &key1, const U &nonkey2
|
||||
, typename disable_if_smartref_to<U, ValuePtr>::type* = 0) const
|
||||
, typename disable_if_smartref_to<U, ValuePtr, sfinae_type*>::type = 0) const
|
||||
{ return this->key_comp()(key1, nonkey2); }
|
||||
|
||||
template<class U>
|
||||
BOOST_INTRUSIVE_FORCEINLINE Ret operator()(const U &nonkey1, const key_type &key2
|
||||
, typename disable_if_smartref_to<U, ValuePtr>::type* = 0) const
|
||||
, typename disable_if_smartref_to<U, ValuePtr, sfinae_type*>::type = 0) const
|
||||
{ return this->key_comp()(nonkey1, key2); }
|
||||
};
|
||||
|
||||
|
94
test/voidptr_key_test.cpp
Normal file
94
test/voidptr_key_test.cpp
Normal file
@@ -0,0 +1,94 @@
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Andrey Semashev 2018.
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// See http://www.boost.org/libs/intrusive for documentation.
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include <boost/intrusive/options.hpp>
|
||||
#include <boost/intrusive/set.hpp>
|
||||
#include <boost/intrusive/set_hook.hpp>
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/core/lightweight_test.hpp>
|
||||
#include <functional> // std::less
|
||||
|
||||
// The test verifies that the set implementation does not use void* as auxiliary arguments for SFINAE
|
||||
// in internal functions, which would make overload resolution ambiguous if user's key type is also void*.
|
||||
|
||||
typedef boost::intrusive::set_base_hook<
|
||||
boost::intrusive::link_mode< boost::intrusive::safe_link >,
|
||||
boost::intrusive::tag< struct for_set_element_lookup_by_key >,
|
||||
boost::intrusive::optimize_size< true >
|
||||
> set_element_hook_t;
|
||||
|
||||
struct set_element :
|
||||
public set_element_hook_t
|
||||
{
|
||||
struct order_by_key
|
||||
{
|
||||
typedef bool result_type;
|
||||
|
||||
result_type operator() (set_element const& left, set_element const& right) const
|
||||
{
|
||||
return std::less< void* >()(left.m_key, right.m_key);
|
||||
}
|
||||
result_type operator() (void* left, set_element const& right) const
|
||||
{
|
||||
return std::less< void* >()(left, right.m_key);
|
||||
}
|
||||
result_type operator() (set_element const& left, void* right) const
|
||||
{
|
||||
return std::less< void* >()(left.m_key, right);
|
||||
}
|
||||
};
|
||||
|
||||
void* m_key;
|
||||
|
||||
explicit set_element(void* key) : m_key(key) {}
|
||||
|
||||
BOOST_DELETED_FUNCTION(set_element(set_element const&))
|
||||
BOOST_DELETED_FUNCTION(set_element& operator=(set_element const&))
|
||||
};
|
||||
|
||||
typedef boost::intrusive::set<
|
||||
set_element,
|
||||
boost::intrusive::base_hook< set_element_hook_t >,
|
||||
boost::intrusive::compare< set_element::order_by_key >,
|
||||
boost::intrusive::constant_time_size< true >
|
||||
> set_t;
|
||||
|
||||
void test_set()
|
||||
{
|
||||
int v1 = 0, v2 = 1, v3 = 2;
|
||||
set_element e1(&v1), e2(&v2), e3(&v3);
|
||||
|
||||
set_t s;
|
||||
s.insert(e1);
|
||||
s.insert(e2);
|
||||
|
||||
set_t::iterator it = s.find(e1);
|
||||
BOOST_TEST(it != s.end() && &*it == &e1);
|
||||
|
||||
it = s.find((void*)&v2, set_element::order_by_key());
|
||||
BOOST_TEST(it != s.end() && &*it == &e2);
|
||||
|
||||
it = s.find(e3);
|
||||
BOOST_TEST(it == s.end());
|
||||
|
||||
it = s.find((void*)&v3, set_element::order_by_key());
|
||||
BOOST_TEST(it == s.end());
|
||||
|
||||
s.clear();
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
test_set();
|
||||
|
||||
return boost::report_errors();
|
||||
}
|
Reference in New Issue
Block a user