Author: | Toon Knapen, David Abrahams, Roland Richter, Jeremy Siek |
---|---|
Contact: | dave@boost-consulting.com, jsiek@osl.iu.edu |
Organization: | Boost Consulting, Indiana University Open Systems Lab |
Date: | 2004-01-12 |
Copyright: | Copyright Toon Knapen, David Abrahams, Roland Richter, and Jeremy Siek 2003. All rights reserved |
abstract: |
---|
The permutation iterator adaptor provides a permuted view of a given range. That is, the view includes every element of the given range but in a potentially different order.
The adaptor takes two arguments:
- an iterator to the range V on which the permutation will be applied
- the reindexing scheme that defines how the elements of V will be permuted.
Note that the permutation iterator is not limited to strict permutations of the given range V. The distance between begin and end of the reindexing iterators is allowed to be smaller compared to the size of the range V, in which case the permutation iterator only provides a permutation of a subrange of V. The indexes neither need to be unique. In this same context, it must be noted that the past the end permutation iterator is completely defined by means of the past-the-end iterator to the indices.
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: permutation_iterator(); explicit permutation_iterator(ElementIterator x, IndexIterator y); template< class OEIter, class OIIter, class V, class C, class R, class D > permutation_iterator( permutation_iterator<OEIter, OIIter, V, C, R, D> const& r , typename enable_if_convertible<OEIter, ElementIterator>::type* = 0 , typename enable_if_convertible<OIIter, IndexIterator>::type* = 0 ); ElementIterator base() const; private: ElementIterator m_iterator; // exposition }; template <class ElementIterator, class IndexIterator> permutation_iterator<ElementIterator, IndexIterator> make_permutation_iterator( ElementIterator e, IndexIterator i);
ElementIterator must be a model of RandomAccessIterator. IndexIterator must at least be a model ForwardIterator. The value type of the IndexIterator must be convertible to the difference type of ElementIterator.
The permutation iterator implements the member functions and operators required for the Random Access Iterator concept. However, the permutation iterator can only meet the complexity guarantees of the same concept as the IndexIterator. Thus for instance, although the permutation iterator provides operator+=(distance), this operation will take linear time in case the IndexIterator is a model of ForwardIterator instead of amortized constant time.
template <class ElementIterator, class IndexIterator> permutation_iterator<ElementIterator, IndexIterator> make_permutation_iterator(ElementIterator e, IndexIterator i);
Returns: | An instance of permutation_iterator<ElementIterator, IndexIterator> that views the range of elements starting at e` in the order given by ``i. |
---|
ElementIterator base() const;
Returns: | m_iterator |
---|
using namespace boost; int i = 0; typedef std::vector< int > element_range_type; typedef std::list< int > index_type; static const int element_range_size = 10; static 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() ); typedef permutation_iterator< element_range_type::iterator, index_type::iterator > permutation_type; permutation_type begin = make_permutation_iterator( elements.begin(), indices.begin() ); permutation_type it = begin; permutation_type end = make_permutation_iterator( elements.begin(), indices.end() ); std::cout << "The original range is : "; std::copy( elements.begin(), elements.end(), std::ostream_iterator< int >( std::cout, " " ) ); std::cout << "\n"; std::cout << "The reindexing scheme is : "; std::copy( indices.begin(), indices.end(), std::ostream_iterator< int >( std::cout, " " ) ); std::cout << "\n"; std::cout << "The permutated range is : "; std::copy( begin, end, std::ostream_iterator< int >( std::cout, " " ) ); std::cout << "\n"; std::cout << "Elements at even indices in the permutation : "; it = begin; for(i = 0; i < index_size / 2 ; ++i, it+=2 ) std::cout << *it << " "; std::cout << "\n"; std::cout << "Permutation backwards : "; it = begin + (index_size); assert( it != begin ); for( ; it-- != begin ; ) std::cout << *it << " "; std::cout << "\n"; std::cout << "Iterate backward with stride 2 : "; it = begin + (index_size - 1); for(i = 0 ; i < index_size / 2 ; ++i, it-=2 ) std::cout << *it << " "; std::cout << "\n";
The output is:
The original range is : 0 1 2 3 4 5 6 7 8 9 The reindexing scheme is : 9 8 7 6 The permutated range is : 9 8 7 6 Elements at even indices in the permutation : 9 7 Permutation backwards : 6 7 8 9 Iterate backward with stride 2 : 6 8
The source code for this example can be found here.