207 lines
6.8 KiB
Plaintext
207 lines
6.8 KiB
Plaintext
|
|
[section:permutation Permutation Iterator]
|
|
|
|
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.
|
|
|
|
[h2 Example]
|
|
|
|
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
|
|
[@../example/permutation_iter_example.cpp here].
|
|
|
|
[h2 Reference]
|
|
|
|
[h3 Synopsis]
|
|
|
|
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
|
|
);
|
|
reference operator*() const;
|
|
permutation_iterator& operator++();
|
|
ElementIterator const& base() const;
|
|
private:
|
|
ElementIterator m_elt; // exposition only
|
|
IndexIterator m_order; // exposition only
|
|
};
|
|
|
|
template <class ElementIterator, class IndexIterator>
|
|
permutation_iterator<ElementIterator, IndexIterator>
|
|
make_permutation_iterator( ElementIterator e, IndexIterator i);
|
|
|
|
|
|
[h3 Requirements]
|
|
|
|
`ElementIterator` shall model Random Access Traversal Iterator.
|
|
`IndexIterator` shall model Readable Iterator. The value type of
|
|
the `IndexIterator` must be convertible to the difference type of
|
|
`ElementIterator`.
|
|
|
|
[h3 Concepts]
|
|
|
|
`permutation_iterator` models the same iterator traversal concepts
|
|
as `IndexIterator` and the same iterator access concepts as
|
|
`ElementIterator`.
|
|
|
|
If `IndexIterator` models Single Pass Iterator and
|
|
`ElementIterator` models Readable Iterator then
|
|
`permutation_iterator` models Input Iterator.
|
|
|
|
If `IndexIterator` models Forward Traversal Iterator and
|
|
`ElementIterator` models Readable Lvalue Iterator then
|
|
`permutation_iterator` models Forward Iterator.
|
|
|
|
If `IndexIterator` models Bidirectional Traversal Iterator and
|
|
`ElementIterator` models Readable Lvalue Iterator then
|
|
`permutation_iterator` models Bidirectional Iterator.
|
|
|
|
If `IndexIterator` models Random Access Traversal Iterator and
|
|
`ElementIterator` models Readable Lvalue Iterator then
|
|
`permutation_iterator` models Random Access Iterator.
|
|
|
|
`permutation_iterator<E1, X, V1, C2, R1, D1>` is interoperable
|
|
with `permutation_iterator<E2, Y, V2, C2, R2, D2>` if and only if
|
|
`X` is interoperable with `Y` and `E1` is convertible
|
|
to `E2`.
|
|
|
|
[h3 Operations]
|
|
|
|
In addition to those operations required by the concepts that
|
|
`permutation_iterator` models, `permutation_iterator` provides the
|
|
following operations.
|
|
|
|
permutation_iterator();
|
|
|
|
[*Effects: ] Default constructs `m_elt` and `m_order`.
|
|
|
|
|
|
explicit permutation_iterator(ElementIterator x, IndexIterator y);
|
|
|
|
[*Effects: ] Constructs `m_elt` from `x` and `m_order` from `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
|
|
);
|
|
|
|
[*Effects: ] Constructs `m_elt` from `r.m_elt` and
|
|
`m_order` from `y.m_order`.
|
|
|
|
|
|
reference operator*() const;
|
|
|
|
[*Returns: ] `*(m_elt + *m_order)`
|
|
|
|
|
|
permutation_iterator& operator++();
|
|
|
|
[*Effects: ] `++m_order`[br]
|
|
[*Returns: ] `*this`
|
|
|
|
|
|
ElementIterator const& base() const;
|
|
|
|
[*Returns: ] `m_order`
|
|
|
|
|
|
template <class ElementIterator, class IndexIterator>
|
|
permutation_iterator<ElementIterator, IndexIterator>
|
|
make_permutation_iterator(ElementIterator e, IndexIterator i);
|
|
|
|
[*Returns: ] `permutation_iterator<ElementIterator, IndexIterator>(e, i)`
|
|
|
|
[endsect] |