Fixed #9948: remove use of const_cast in intrusive containers.

Added tests for [s_]iterator_to.
This commit is contained in:
Ion Gaztañaga
2014-05-01 16:19:42 +02:00
parent 95dcc3bade
commit 7fc779ff0d
6 changed files with 57 additions and 20 deletions

View File

@@ -3792,13 +3792,15 @@ to be inserted in intrusive containers are allocated using `std::vector` or `std
* [*Source breaking]: Removed previously deprecated `xxx_dont_splay` functions from splay containers,
`splay_set_base_hook` and `splay_set_member_hook`from splay containers and `bool splay = true`
extra parameter is `splaytree_algorithms` functions.
extra parameter in `splaytree_algorithms` functions.
* Fixed bugs:
* [@https://svn.boost.org/trac/boost/ticket/8468 #8468: Compile error on visual studio 2010/2012 using vector with custom allocator and aligned types]
* [@https://svn.boost.org/trac/boost/ticket/9332 #9332: ['"has_member_function_callable_with.hpp compile error on msvc-12.0"]].
* [@https://svn.boost.org/trac/boost/ticket/9650 #9650: ['"intrusive list with stateful value traits"]].
* [@https://svn.boost.org/trac/boost/ticket/9746 #9746: Modern Sun CC compiler detects error in intrusive library header]
* [@https://svn.boost.org/trac/boost/ticket/9940 #9940: bad bug in intrusive list with safe_link (or auto_unlink) hooks]
* [@https://svn.boost.org/trac/boost/ticket/9948 #9948: remove use of const_cast in intrusive containers]
* [@https://svn.boost.org/trac/boost/ticket/9949 #9949: clear header node hooks upon intrusive container destruction]
* [@https://svn.boost.org/trac/boost/ticket/9961 #9961: tests for hooks not derived frorm generic_hook]

View File

@@ -1103,6 +1103,13 @@ class hashtable_impl
typedef typename pointer_traits
<pointer>::template rebind_pointer
< bucket_type >::type bucket_ptr;
typedef typename pointer_traits
<pointer>::template rebind_pointer
< const bucket_type >::type const_bucket_ptr;
typedef typename pointer_traits
<bucket_ptr>::reference bucket_reference;
typedef typename pointer_traits
<bucket_ptr>::reference const_bucket_reference;
typedef typename slist_impl::iterator siterator;
typedef typename slist_impl::const_iterator const_siterator;
typedef hashtable_iterator<bucket_plus_vtraits_t, false> iterator;
@@ -1115,6 +1122,10 @@ class hashtable_impl
typedef typename pointer_traits
<pointer>::template rebind_pointer
< const node >::type const_node_ptr;
typedef typename pointer_traits
<node_ptr>::reference node_reference;
typedef typename pointer_traits
<const_node_ptr>::reference const_node_reference;
typedef typename slist_impl::node_algorithms node_algorithms;
static const bool stateful_value_traits = detail::is_stateful_value_traits<value_traits>::value;
@@ -2145,7 +2156,9 @@ class hashtable_impl
//! <b>Throws</b>: If the internal hash function throws.
const_iterator iterator_to(const_reference value) const
{
siterator sit = bucket_type::s_iterator_to(const_cast<node &>(this->priv_value_to_node(value)));
node_reference r = *pointer_traits<node_ptr>::const_cast_from
(pointer_traits<const_node_ptr>::pointer_to(this->priv_value_to_node(value)));
siterator sit = bucket_type::s_iterator_to(r);
return const_iterator(sit, &this->get_bucket_value_traits());
}
@@ -2183,7 +2196,9 @@ class hashtable_impl
static const_local_iterator s_local_iterator_to(const_reference value)
{
BOOST_STATIC_ASSERT((!stateful_value_traits));
siterator sit = bucket_type::s_iterator_to(((hashtable_impl*)0)->priv_value_to_node(const_cast<value_type&>(value)));
node_reference r = *pointer_traits<node_ptr>::const_cast_from
(pointer_traits<const_node_ptr>::pointer_to(((hashtable_impl*)0)->priv_value_to_node(value)));
siterator sit = bucket_type::s_iterator_to(r);
return const_local_iterator(sit, const_value_traits_ptr());
}
@@ -2213,8 +2228,9 @@ class hashtable_impl
//! <b>Throws</b>: Nothing.
const_local_iterator local_iterator_to(const_reference value) const
{
siterator sit = bucket_type::s_iterator_to
(const_cast<node &>(this->priv_value_to_node(value)));
node_reference r = *pointer_traits<node_ptr>::const_cast_from
(pointer_traits<const_node_ptr>::pointer_to(this->priv_value_to_node(value)));
siterator sit = bucket_type::s_iterator_to(r);
return const_local_iterator(sit, this->value_traits_ptr());
}
@@ -2314,8 +2330,8 @@ class hashtable_impl
//! containing all of the elements in the nth bucket.
const_local_iterator cbegin(size_type n) const
{
siterator sit = const_cast<bucket_type&>(this->priv_bucket_pointer()[n]).begin();
return const_local_iterator(sit, this->value_traits_ptr());
bucket_reference br = pointer_traits<bucket_ptr>::const_cast_from(this->priv_bucket_pointer())[n];
return const_local_iterator(br.begin(), this->value_traits_ptr());
}
//! <b>Requires</b>: n is in the range [0, this->bucket_count()).
@@ -2359,8 +2375,8 @@ class hashtable_impl
//! containing all of the elements in the nth bucket.
const_local_iterator cend(size_type n) const
{
return const_local_iterator ( const_cast<bucket_type&>(this->priv_bucket_pointer()[n]).end()
, this->value_traits_ptr());
bucket_reference br = pointer_traits<bucket_ptr>::const_cast_from(this->priv_bucket_pointer())[n];
return const_local_iterator ( br.end(), this->value_traits_ptr());
}
//! <b>Requires</b>: new_bucket_traits can hold a pointer to a new bucket array

View File

@@ -1213,8 +1213,9 @@ class list_impl
static const_iterator s_iterator_to(const_reference value)
{
BOOST_STATIC_ASSERT((!stateful_value_traits));
BOOST_INTRUSIVE_INVARIANT_ASSERT(!node_algorithms::inited(value_traits::to_node_ptr(*pointer_traits<pointer>::const_cast_from(pointer_traits<const_pointer>::pointer_to(value)))));
return const_iterator(value_traits::to_node_ptr(*pointer_traits<pointer>::const_cast_from(pointer_traits<const_pointer>::pointer_to(value))), const_value_traits_ptr());
reference r =*pointer_traits<pointer>::const_cast_from(pointer_traits<const_pointer>::pointer_to(value));
BOOST_INTRUSIVE_INVARIANT_ASSERT(!node_algorithms::inited(value_traits::to_node_ptr(r)));
return const_iterator(value_traits::to_node_ptr(r), const_value_traits_ptr());
}
//! <b>Requires</b>: value must be a reference to a value inserted in a list.
@@ -1243,8 +1244,9 @@ class list_impl
//! <b>Note</b>: Iterators and references are not invalidated.
const_iterator iterator_to(const_reference value) const
{
BOOST_INTRUSIVE_INVARIANT_ASSERT(!node_algorithms::inited(this->priv_value_traits().to_node_ptr(*pointer_traits<pointer>::const_cast_from(pointer_traits<const_pointer>::pointer_to(value)))));
return const_iterator(this->priv_value_traits().to_node_ptr(*pointer_traits<pointer>::const_cast_from(pointer_traits<const_pointer>::pointer_to(value))), value_traits_ptr());
reference r = *pointer_traits<pointer>::const_cast_from(pointer_traits<const_pointer>::pointer_to(value));
BOOST_INTRUSIVE_INVARIANT_ASSERT(!node_algorithms::inited(this->priv_value_traits().to_node_ptr(r)));
return const_iterator(this->priv_value_traits().to_node_ptr(r), value_traits_ptr());
}
/// @cond

View File

@@ -1685,7 +1685,8 @@ class slist_impl
static const_iterator s_iterator_to(const_reference value)
{
BOOST_STATIC_ASSERT((!stateful_value_traits));
return const_iterator(value_traits::to_node_ptr(*pointer_traits<pointer>::const_cast_from(pointer_traits<const_pointer>::pointer_to(value))), const_value_traits_ptr());
reference r =*pointer_traits<pointer>::const_cast_from(pointer_traits<const_pointer>::pointer_to(value));
return const_iterator(value_traits::to_node_ptr(r), const_value_traits_ptr());
}
//! <b>Requires</b>: value must be a reference to a value inserted in a list.
@@ -1714,8 +1715,9 @@ class slist_impl
//! <b>Note</b>: Iterators and references are not invalidated.
const_iterator iterator_to(const_reference value) const
{
BOOST_INTRUSIVE_INVARIANT_ASSERT (linear || !node_algorithms::inited(this->priv_value_traits().to_node_ptr(*pointer_traits<pointer>::const_cast_from(pointer_traits<const_pointer>::pointer_to(value)))));
return const_iterator(this->priv_value_traits().to_node_ptr(*pointer_traits<pointer>::const_cast_from(pointer_traits<const_pointer>::pointer_to(value))), this->value_traits_ptr());
reference r =*pointer_traits<pointer>::const_cast_from(pointer_traits<const_pointer>::pointer_to(value));
BOOST_INTRUSIVE_INVARIANT_ASSERT (linear || !node_algorithms::inited(this->priv_value_traits().to_node_ptr(r)));
return const_iterator(this->priv_value_traits().to_node_ptr(r), this->value_traits_ptr());
}
//! <b>Returns</b>: The iterator to the element before i in the list.

View File

@@ -232,9 +232,6 @@
<File
RelativePath="..\..\..\..\..\boost\intrusive\detail\assert.hpp">
</File>
<File
RelativePath="..\..\..\..\..\boost\intrusive\detail\clear_on_destructor_base.hpp">
</File>
<File
RelativePath="..\..\..\..\..\boost\intrusive\detail\common_slist_algorithms.hpp">
</File>

View File

@@ -90,6 +90,10 @@ void test_sequence_container(Container & c, Data & d)
{
typename Data::iterator i = d.begin();
c.insert( c.begin(), *i );
BOOST_TEST( &*c.iterator_to(*c.begin()) == &*i );
BOOST_TEST( &*c.iterator_to(*c.cbegin()) == &*i );
BOOST_TEST( &*Container::s_iterator_to(*c.begin()) == &*i );
BOOST_TEST( &*Container::s_iterator_to(*c.cbegin()) == &*i );
c.insert( c.end(), *(++i) );
}
BOOST_TEST( c.size() == 2 );
@@ -230,6 +234,12 @@ void test_common_unordered_and_associative_container(Container & c, Data & d, bo
assert( d.size() > 2 );
c.clear();
typename Container::reference r = *d.begin();
c.insert(d.begin(), ++d.begin());
BOOST_TEST( &*Container::s_iterator_to(*c.begin()) == &r );
BOOST_TEST( &*Container::s_iterator_to(*c.cbegin()) == &r );
c.clear();
c.insert(d.begin(), d.end());
@@ -259,7 +269,6 @@ void test_common_unordered_and_associative_container(Container & c, Data & d, bo
BOOST_TEST( c.equal_range(*da, c.key_comp()).first == c.end() );
}
template< class Container, class Data >
void test_common_unordered_and_associative_container(Container & c, Data & d)
{
@@ -267,6 +276,12 @@ void test_common_unordered_and_associative_container(Container & c, Data & d)
{
assert( d.size() > 2 );
c.clear();
typename Container::reference r = *d.begin();
c.insert(d.begin(), ++d.begin());
BOOST_TEST( &*c.iterator_to(*c.begin()) == &r );
BOOST_TEST( &*c.iterator_to(*c.cbegin()) == &r );
c.clear();
c.insert(d.begin(), d.end());
@@ -372,6 +387,9 @@ void test_unordered_associative_container_invariants(Container & c, Data & d)
size_type bucket_elem = std::distance(c.begin(nb), c.end(nb));
BOOST_TEST( bucket_elem == c.bucket_size(nb) );
BOOST_TEST( &*c.local_iterator_to(*c.find(*di)) == &*i );
BOOST_TEST( &*c.local_iterator_to(*const_cast<const Container &>(c).find(*di)) == &*i );
BOOST_TEST( &*Container::s_local_iterator_to(*c.find(*di)) == &*i );
BOOST_TEST( &*Container::s_local_iterator_to(*const_cast<const Container &>(c).find(*di)) == &*i );
std::pair<const_iterator, const_iterator> er = c.equal_range(*di);
size_type cnt = std::distance(er.first, er.second);
BOOST_TEST( cnt == c.count(*di));