From 17c0fa271c6926a4aa67254686c9559208ac040a Mon Sep 17 00:00:00 2001 From: Neil Groves Date: Mon, 3 Mar 2014 01:24:56 +0000 Subject: [PATCH] trac 9515 - fix for uniqued adaptor consistent with unique algorithm. --- .../boost/range/adaptor/adjacent_filtered.hpp | 58 ++++++-------- test/adaptor_test/uniqued.cpp | 79 +++++++++++++++++++ 2 files changed, 103 insertions(+), 34 deletions(-) diff --git a/include/boost/range/adaptor/adjacent_filtered.hpp b/include/boost/range/adaptor/adjacent_filtered.hpp index f717cb3..159d8ee 100644 --- a/include/boost/range/adaptor/adjacent_filtered.hpp +++ b/include/boost/range/adaptor/adjacent_filtered.hpp @@ -62,54 +62,44 @@ namespace boost , pred_t(pred) , m_last(last) { - move_to_next_valid(); } template skip_iterator( const skip_iterator& other ) : base_t(other.base()) , pred_t(other) - , m_last(other.m_last) {} - - void move_to_next_valid() + , m_last(other.m_last) { - iter_t& it = this->base_reference(); - pred_t& bi_pred = *this; - if (it != m_last) - { - if (default_pass) - { - iter_t nxt = ::boost::next(it); - while (nxt != m_last && !bi_pred(*it, *nxt)) - { - ++it; - ++nxt; - } - } - else - { - iter_t nxt = ::boost::next(it); - for(; nxt != m_last; ++it, ++nxt) - { - if (bi_pred(*it, *nxt)) - { - break; - } - } - if (nxt == m_last) - { - it = m_last; - } - } - } } void increment() { iter_t& it = this->base_reference(); BOOST_ASSERT( it != m_last ); + pred_t& bi_pred = *this; + iter_t prev = it; ++it; - move_to_next_valid(); + if (it != m_last) + { + if (default_pass) + { + while (it != m_last && !bi_pred(*prev, *it)) + { + ++it; + ++prev; + } + } + else + { + for (; it != m_last; ++it, ++prev) + { + if (bi_pred(*prev, *it)) + { + break; + } + } + } + } } iter_t m_last; diff --git a/test/adaptor_test/uniqued.cpp b/test/adaptor_test/uniqued.cpp index 9c96744..fdf5454 100644 --- a/test/adaptor_test/uniqued.cpp +++ b/test/adaptor_test/uniqued.cpp @@ -9,6 +9,10 @@ // For more information, see http://www.boost.org/libs/range/ // #include +#include +#include +#include +#include #include #include @@ -74,9 +78,82 @@ namespace boost uniqued_test_impl< std::set< int > >(); uniqued_test_impl< std::multiset< int > >(); } + +class istring +{ +public: + istring() + : m_value("") + { } + + explicit istring(const char* value) + : m_value(value) + { + } + + bool operator==(istring r) const + { + return boost::iequals(m_value, r.m_value); + } + + bool operator!=(istring r) const + { + return !operator==(r); + } + + inline friend std::ostream& operator<<(std::ostream& out, istring o) + { + return out << o.m_value; + } + + const char* get() const { return m_value; } + +private: + const char* m_value; +}; + +struct istring_to_string +{ + typedef std::string result_type; + + std::string operator()(istring s) const + { + return s.get(); + } +}; + +// This is based on a test-case provided by Eric Neibler. +void uniqued_return_first() +{ + using namespace boost::adaptors; + + std::vector strs; + strs.push_back(istring("hello")); + strs.push_back(istring("hElLo")); + strs.push_back(istring("HELLO")); + strs.push_back(istring("ZZZZ")); + + std::vector output1; + + boost::unique_copy(strs, std::back_inserter(output1)); + + std::vector output2; + boost::push_back(output2, strs | uniqued); + + std::vector test1; + boost::push_back(test1, output1 | transformed(istring_to_string())); + + std::vector test2; + boost::push_back(test2, output2 | transformed(istring_to_string())); + + BOOST_CHECK_EQUAL_COLLECTIONS(test1.begin(), test1.end(), + test2.begin(), test2.end()); } + } // anonymous namespace +} // namespace boost + boost::unit_test::test_suite* init_unit_test_suite(int argc, char* argv[]) { @@ -85,5 +162,7 @@ init_unit_test_suite(int argc, char* argv[]) test->add( BOOST_TEST_CASE( &boost::uniqued_test ) ); + test->add(BOOST_TEST_CASE(&boost::uniqued_return_first)); + return test; }