From fd37912e30c5be9084b20b1e3b2846c9c2ed82ba Mon Sep 17 00:00:00 2001 From: Roland Richter Date: Fri, 13 Jun 2003 08:15:30 +0000 Subject: [PATCH] Rewrite to work with new iterator_adaptors. [SVN r1360] --- .../boost/iterator/permutation_iterator.hpp | 92 ++++++++++++++++ test/permutation_iterator_test.cpp | 101 ++++++++++++++++++ 2 files changed, 193 insertions(+) create mode 100644 include/boost/iterator/permutation_iterator.hpp create mode 100644 test/permutation_iterator_test.cpp diff --git a/include/boost/iterator/permutation_iterator.hpp b/include/boost/iterator/permutation_iterator.hpp new file mode 100644 index 0000000..f41da1a --- /dev/null +++ b/include/boost/iterator/permutation_iterator.hpp @@ -0,0 +1,92 @@ +// (C) Copyright Toon Knapen 2001. +// (C) Copyright David Abrahams 2003. +// (C) Copyright Roland Richter 2003. +// Permission to copy, use, modify, sell and distribute this software +// is granted provided this copyright notice appears in all copies. +// This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. + +#ifndef BOOST_PERMUTATION_ITERATOR_HPP +#define BOOST_PERMUTATION_ITERATOR_HPP + +#include + +#include + + +namespace boost +{ + +template< class ElementIterator + , class IndexIterator + , class ValueT = use_default + , class CategoryT = use_default + , class ReferenceT = use_default + , class DifferenceT = use_default > +class permutation_iterator + : public iterator_adaptor< + permutation_iterator + , ElementIterator, ValueT, CategoryT, ReferenceT, DifferenceT > +{ + typedef iterator_adaptor< + permutation_iterator + , ElementIterator, ValueT, CategoryT, ReferenceT, DifferenceT > super_t; + + friend class iterator_core_access; + +public: + permutation_iterator() : order_it_() {} + + explicit permutation_iterator(ElementIterator x, IndexIterator y) + : super_t(x), order_it_(y) {} + + template + permutation_iterator( + permutation_iterator const& r + , typename enable_if_convertible::type* = 0 + , typename enable_if_convertible::type* = 0 + ) + : super_t(r.base()) + {} + +private: + typename super_t::reference dereference() const + { return *(this->base() + *this->order_it_); } + + void increment() { ++this->order_it_; } + void decrement() { --this->order_it_; } + + void advance(typename super_t::difference_type n) + { + std::advance( order_it_, n ); + } + + template + typename super_t::difference_type + distance_to( permutation_iterator const& y ) const + { + return std::distance( this->order_it_, y.order_it_ ); + } + + template + bool + equal( permutation_iterator const& y ) const + { + return( y.order_it_ == this->order_it_ ); + } + + IndexIterator order_it_; +}; + + +template +permutation_iterator +make_permutation_iterator( ElementIterator e, IndexIterator i ) +{ + return permutation_iterator( e, i ); +} + + +} // namespace boost + +#endif diff --git a/test/permutation_iterator_test.cpp b/test/permutation_iterator_test.cpp new file mode 100644 index 0000000..0b05ba2 --- /dev/null +++ b/test/permutation_iterator_test.cpp @@ -0,0 +1,101 @@ +// (C) Copyright Toon Knapen 2001. +// (C) Copyright Roland Richter 2003. +// Permission to copy, use, modify, sell and distribute this software +// is granted provided this copyright notice appears in all copies. +// This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. + +#include +#include + +#include + +#include +#include + +#include + + +void permutation_test() +{ + // Example taken from documentation of old permutation_iterator. + typedef std::vector< int > element_range_type; + typedef std::list< int > index_type; + + const int element_range_size = 10; + const int index_size = 4; + + element_range_type elements( element_range_size ); + for( element_range_type::iterator el_it = elements.begin(); el_it != elements.end(); ++el_it ) + { *el_it = std::distance(elements.begin(), el_it); } + + index_type indices( index_size ); + for( index_type::iterator i_it = indices.begin(); i_it != indices.end(); ++i_it ) + { *i_it = element_range_size - index_size + std::distance(indices.begin(), i_it); } + std::reverse( indices.begin(), indices.end() ); + +#ifdef BOOST_MSVC + + typedef boost::permutation_iterator< element_range_type::iterator + , index_type::iterator + , boost::use_default + , boost::use_default + , element_range_type::reference > permutation_type; + + permutation_type begin( elements.begin(), indices.begin() ); + permutation_type it = begin; + permutation_type end( elements.begin(), indices.end() ); + +#else + + typedef boost::permutation_iterator< element_range_type::iterator, index_type::iterator > permutation_type; + permutation_type begin = boost::make_permutation_iterator( elements.begin(), indices.begin() ); + permutation_type it = begin; + permutation_type end = boost::make_permutation_iterator( elements.begin(), indices.end() ); + +#endif + + BOOST_CHECK( it == begin ); + BOOST_CHECK( it != end ); + + BOOST_CHECK( std::distance( begin, end ) == index_size ); + + for( index_type::iterator i_it = indices.begin(); it != end; ++i_it, ++it ) + { + BOOST_CHECK( *it == elements[ *i_it ] ); + } + + it = begin; + for( int i = 0; i < index_size ; i+=2, it+=2 ) + { + index_type::iterator i_it = indices.begin(); std::advance( i_it, i ); + BOOST_CHECK( *it == elements[ *i_it ] ); + } + + + it = begin + (index_size); + BOOST_CHECK( it != begin ); + for( index_type::iterator i_it = --indices.end(); it-- != begin; --i_it ) + { + BOOST_CHECK( *it == elements[ *i_it ] ); + } + + it = begin + (index_size - 1); + for( int i = 0; i < index_size; i+=2, it-=2 ) + { + index_type::iterator i_it = --indices.end(); std::advance( i_it, -i ); + BOOST_CHECK( *it == elements[ *i_it ] ); + } + +} + + +int test_main(int, char *[]) +{ + permutation_test(); + + bool error_on_purpose = false; + //BOOST_CHECK( error_on_purpose ); + + return 0; +}