forked from boostorg/container
RandomAccessIterator + 0
Previously the iterators of boost::container::deque would assert when zero was added to them in at least the following situations: - The iterator was obtained by a call to boost::container::deque::begin and boost::container::deque::empty returns true - The iterator was default constructed This is inconsistent with the way in which the iterators of boost:: container::deque have behaved historically and is also inconsistent with an understanding of iterators developed by analogy with pointers: - Adding zero to a null pointer is valid despite the fact the null pointer cannot be dereferenced - Adding zero to a pointer that is one past the end yields a pointer which is still one past the end and thus which has well defined semantics Fixed this issue and codified the expected behavior in unit tests.
This commit is contained in:
@@ -234,6 +234,8 @@ class deque_iterator
|
||||
|
||||
deque_iterator& operator+=(difference_type n) BOOST_NOEXCEPT_OR_NOTHROW
|
||||
{
|
||||
if (!n)
|
||||
return *this;
|
||||
BOOST_ASSERT(!!m_cur);
|
||||
difference_type offset = n + (this->m_cur - this->m_first);
|
||||
const difference_type block_size = this->m_last - this->m_first;
|
||||
|
@@ -24,6 +24,7 @@
|
||||
#include <boost/core/lightweight_test.hpp>
|
||||
#include <boost/static_assert.hpp>
|
||||
#include <cstring>
|
||||
#include <iterator>
|
||||
#include <new>
|
||||
|
||||
using namespace boost::container;
|
||||
@@ -56,6 +57,40 @@ BOOST_INTRUSIVE_INSTANTIATE_DEFAULT_TYPE_TMPLT(const_reverse_iterator)
|
||||
|
||||
}}} //namespace boost::container::test {
|
||||
|
||||
template<class RandomAccessIterator>
|
||||
void check_plus_zero_impl(RandomAccessIterator it)
|
||||
{
|
||||
RandomAccessIterator cpy(it + 0);
|
||||
BOOST_TEST(cpy == it);
|
||||
}
|
||||
|
||||
template<class Container, class Category>
|
||||
void check_plus_zero(const Category&)
|
||||
{}
|
||||
|
||||
template<class Container>
|
||||
void check_plus_zero(const std::random_access_iterator_tag&)
|
||||
{
|
||||
check_plus_zero_impl(typename Container::iterator());
|
||||
check_plus_zero_impl(typename Container::const_iterator());
|
||||
check_plus_zero_impl(typename Container::reverse_iterator());
|
||||
check_plus_zero_impl(typename Container::const_reverse_iterator());
|
||||
Container c;
|
||||
check_plus_zero_impl(c.begin());
|
||||
check_plus_zero_impl(c.cbegin());
|
||||
check_plus_zero_impl(c.rbegin());
|
||||
check_plus_zero_impl(c.crbegin());
|
||||
}
|
||||
|
||||
template<class Container>
|
||||
void check_plus_zero()
|
||||
{
|
||||
typedef typename Container::iterator iterator;
|
||||
typedef typename std::iterator_traits<iterator>::iterator_category category;
|
||||
category tag;
|
||||
check_plus_zero<Container>(tag);
|
||||
}
|
||||
|
||||
template<class Container>
|
||||
void check_null_iterators()
|
||||
{
|
||||
@@ -77,20 +112,35 @@ void check_null_iterators()
|
||||
int main()
|
||||
{
|
||||
check_null_iterators< vector<int> >();
|
||||
check_plus_zero< vector<int> >();
|
||||
check_null_iterators< deque<int> >();
|
||||
check_plus_zero< deque<int> >();
|
||||
check_null_iterators< stable_vector<int> >();
|
||||
check_plus_zero< stable_vector<int> >();
|
||||
check_null_iterators< static_vector<int, 1> >();
|
||||
check_plus_zero< static_vector<int, 1> >();
|
||||
check_null_iterators< string >();
|
||||
check_plus_zero< string >();
|
||||
check_null_iterators< list<int> >();
|
||||
check_plus_zero< list<int> >();
|
||||
check_null_iterators< slist<int> >();
|
||||
check_plus_zero< slist<int> >();
|
||||
check_null_iterators< map<int, int> >();
|
||||
check_plus_zero< map<int, int> >();
|
||||
check_null_iterators< multimap<int, int> >();
|
||||
check_plus_zero< multimap<int, int> >();
|
||||
check_null_iterators< set<int> >();
|
||||
check_plus_zero< set<int> >();
|
||||
check_null_iterators< multiset<int> >();
|
||||
check_plus_zero< multiset<int> >();
|
||||
check_null_iterators< flat_set<int> >();
|
||||
check_plus_zero< flat_set<int> >();
|
||||
check_null_iterators< flat_multiset<int> >();
|
||||
check_plus_zero< flat_multiset<int> >();
|
||||
check_null_iterators< flat_map<int, int> >();
|
||||
check_plus_zero< flat_map<int, int> >();
|
||||
check_null_iterators< flat_multimap<int, int> >();
|
||||
check_plus_zero< flat_multimap<int, int> >();
|
||||
|
||||
return boost::report_errors();
|
||||
}
|
||||
|
Reference in New Issue
Block a user