From 69759731bb5e55b92052e6f6d7d3efdb049f037b Mon Sep 17 00:00:00 2001 From: Neil Groves Date: Tue, 4 Mar 2014 15:05:00 +0000 Subject: [PATCH 1/2] implemented drop_front and drop_back with test. --- include/boost/range/iterator_range_core.hpp | 35 ++-- test/Jamfile.v2 | 1 + test/iterator_range_drop.cpp | 200 ++++++++++++++++++++ 3 files changed, 219 insertions(+), 17 deletions(-) create mode 100644 test/iterator_range_drop.cpp diff --git a/include/boost/range/iterator_range_core.hpp b/include/boost/range/iterator_range_core.hpp index 7bbae2a..e30f1a6 100644 --- a/include/boost/range/iterator_range_core.hpp +++ b/include/boost/range/iterator_range_core.hpp @@ -206,12 +206,18 @@ public: return *m_Begin; } - void pop_front() + void drop_front() { BOOST_ASSERT(!empty()); ++m_Begin; } + void drop_front(difference_type n) + { + BOOST_ASSERT(n >= difference_type()); + std::advance(this->m_Begin, n); + } + protected: template void assign(Iterator first, Iterator last) @@ -256,17 +262,26 @@ protected: } public: - BOOST_DEDUCED_TYPENAME base_type::reference back() const + typedef BOOST_DEDUCED_TYPENAME base_type::difference_type difference_type; + typedef BOOST_DEDUCED_TYPENAME base_type::reference reference; + + reference back() const { BOOST_ASSERT(!this->empty()); return *boost::prior(this->m_End); } - void pop_back() + void drop_back() { BOOST_ASSERT(!this->empty()); --this->m_End; } + + void drop_back(difference_type n) + { + BOOST_ASSERT(n >= difference_type()); + std::advance(this->m_End, -n); + } }; template @@ -328,20 +343,6 @@ public: return this->m_Begin[at]; } - void pop_front(difference_type n) - { - BOOST_ASSERT(n >= difference_type()); - BOOST_ASSERT(size() >= static_cast(n)); - std::advance(this->m_Begin, n); - } - - void pop_back(difference_type n) - { - BOOST_ASSERT(n >= difference_type()); - BOOST_ASSERT(size() >= static_cast(n)); - std::advance(this->m_End, -n); - } - BOOST_DEDUCED_TYPENAME base_type::size_type size() const { return this->m_End - this->m_Begin; diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index a7b479a..8b9463e 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -160,6 +160,7 @@ test-suite range : [ range-test istream_range ] [ range-test iterator_pair ] [ range-test iterator_range ] + [ range-test iterator_range_drop ] [ range-test iterator_range_variant ] # [ range-test mfc : $(VC71_ROOT)/atlmfc/include ] [ range-test join ] diff --git a/test/iterator_range_drop.cpp b/test/iterator_range_drop.cpp new file mode 100644 index 0000000..3b41041 --- /dev/null +++ b/test/iterator_range_drop.cpp @@ -0,0 +1,200 @@ +// Boost.Range library +// +// Copyright Neil Groves 2014. Use, modification and +// distribution is subject to 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) +// +// For more information, see http://www.boost.org/libs/range/ +// + +#include +#include +#include + +#include +#include + +#include + +namespace boost_range_test +{ + namespace + { + +class single_pass_iterator + : public boost::iterator_facade< + single_pass_iterator, + boost::int32_t, + boost::single_pass_traversal_tag, + const boost::int32_t& + > +{ + friend class boost::iterator_core_access; + + typedef std::vector::const_iterator iterator_t; + +public: + single_pass_iterator() { } + + explicit single_pass_iterator(iterator_t it) + : m_it(it) + { + } + +private: + void increment() + { + ++m_it; + } + + bool equal(single_pass_iterator other) const + { + return m_it == other.m_it; + } + + boost::int32_t dereference() const + { + return *m_it; + } + + iterator_t m_it; +}; + +class bidirectional_iterator + : public boost::iterator_facade< + bidirectional_iterator, + boost::int32_t, + boost::bidirectional_traversal_tag, + const boost::int32_t& + > +{ + friend class boost::iterator_core_access; + + typedef std::vector::const_iterator iterator_t; + +public: + bidirectional_iterator() { } + + explicit bidirectional_iterator(iterator_t it) + : m_it(it) + { + } + +private: + void increment() + { + ++m_it; + } + + void decrement() + { + --m_it; + } + + bool equal(bidirectional_iterator other) const + { + return m_it == other.m_it; + } + + boost::int32_t dereference() const + { + return *m_it; + } + + iterator_t m_it; +}; + +template +boost::iterator_range +single_pass_range(const SinglePassRange& rng) +{ + return boost::iterator_range( + single_pass_iterator(boost::begin(rng)), + single_pass_iterator(boost::end(rng))); +} + +template +boost::iterator_range +bidirectional_range(const BidirectionalRange& rng) +{ + return boost::iterator_range( + bidirectional_iterator(boost::begin(rng)), + bidirectional_iterator(boost::end(rng))); +} + +void test_drop_front() +{ + std::vector v; + std::vector ref_output; + + for (boost::int32_t i = 0; i < 10; ++i) + { + v.push_back(i); + ref_output.push_back(i); + } + + boost::iterator_range rng = single_pass_range(v); + + BOOST_CHECK_EQUAL_COLLECTIONS(rng.begin(), rng.end(), + ref_output.begin(), ref_output.end()); + + rng.drop_front(); + + ref_output.erase(ref_output.begin()); + + BOOST_CHECK_EQUAL_COLLECTIONS(rng.begin(), rng.end(), + ref_output.begin(), ref_output.end()); + + rng.drop_front(5); + + ref_output.erase(ref_output.begin(), ref_output.begin() + 5); + + BOOST_CHECK_EQUAL_COLLECTIONS(rng.begin(), rng.end(), + ref_output.begin(), ref_output.end()); +} + +void test_drop_back() +{ + std::vector v; + std::vector ref_output; + + for (boost::int32_t i = 0; i < 10; ++i) + { + v.push_back(i); + ref_output.push_back(i); + } + + boost::iterator_range rng = bidirectional_range(v); + + BOOST_CHECK_EQUAL_COLLECTIONS(rng.begin(), rng.end(), + ref_output.begin(), ref_output.end()); + + rng.drop_back(); + + ref_output.pop_back(); + + BOOST_CHECK_EQUAL_COLLECTIONS(rng.begin(), rng.end(), + ref_output.begin(), ref_output.end()); + + rng.drop_back(5); + + ref_output.erase(ref_output.end() - 5, ref_output.end()); + + BOOST_CHECK_EQUAL_COLLECTIONS(rng.begin(), rng.end(), + ref_output.begin(), ref_output.end()); +} + + } // anonymous namespace +} // namespace boost_range_test + +boost::unit_test::test_suite* init_unit_test_suite( int argc, char* argv[] ) +{ + boost::unit_test::test_suite* test = + BOOST_TEST_SUITE("Boost.Range iterator_range drop functions"); + + test->add(BOOST_TEST_CASE(&boost_range_test::test_drop_front)); + test->add(BOOST_TEST_CASE(&boost_range_test::test_drop_back)); + + return test; +} From 09cc98f60d355778330482f7416ebfdffe66bd32 Mon Sep 17 00:00:00 2001 From: Neil Groves Date: Tue, 4 Mar 2014 16:19:51 +0000 Subject: [PATCH 2/2] drop_front and drop_back included in synopsis. --- doc/reference/utilities.qbk | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/doc/reference/utilities.qbk b/doc/reference/utilities.qbk index 0da1f52..b0d9f07 100644 --- a/doc/reference/utilities.qbk +++ b/doc/reference/utilities.qbk @@ -61,11 +61,14 @@ namespace boost operator unspecified_bool_type() const; bool equal( const iterator_range& ) const; value_type& front() const; - value_type& back() const; - iterator_range& advance_begin(difference_type n); - iterator_range& advance_end(difference_type n); + void drop_front(); + void drop_front(difference_type n); bool empty() const; - // for Random Access Range only: + // for Bidirectional: + value_type& back() const; + void drop_back(); + void drop_back(difference_type n); + // for Random Access only: reference operator[]( difference_type at ) const; value_type operator()( difference_type at ) const; size_type size() const; @@ -230,21 +233,6 @@ namespace boost template< class ForwardRange2 > sub_range& operator=( const ForwardRange2& r ); - public: // Forward Range functions - iterator begin(); - const_iterator begin() const; - iterator end(); - const_iterator end() const; - - public: // convenience - value_type& front(); - const value_type& front() const; - value_type& back(); - const value_type& back() const; - // for Random Access Range only: - value_type& operator[]( size_type at ); - const value_type& operator[]( size_type at ) const; - public: // rest of interface inherited from iterator_range };