Compare commits

...

10 Commits

Author SHA1 Message Date
0d612a730d This commit was manufactured by cvs2svn to create tag
'Version_1_26_0'.

[SVN r11842]
2001-11-30 18:24:42 +00:00
50a502bb81 uses proper template argument names : ElementIterator and IndexIterator
[SVN r11826]
2001-11-30 11:14:24 +00:00
8a4839354e permutation_iterator_adaptor and generator
[SVN r11823]
2001-11-30 10:38:36 +00:00
4da7371246 *** empty log message ***
[SVN r11611]
2001-11-06 15:52:56 +00:00
e162a75e53 *** empty log message ***
[SVN r11609]
2001-11-06 15:28:04 +00:00
e60df6ad92 Workarounds for CWPro7, MSVC
Changed all "bind" to "select" (again), to avoid conflicting with Peter Dimov's code.


[SVN r11590]
2001-11-05 16:33:40 +00:00
4c2b3a9d2c Cleanups for MWERKS, without changing functionality
[SVN r11585]
2001-11-05 15:25:45 +00:00
75023a1dd3 Fixed comparison bugs; more remain.
[SVN r11581]
2001-11-05 06:25:31 +00:00
79370a6dfb non-named parameter version of some BGL algorithms
some VC++ compiler stuff


[SVN r11576]
2001-11-04 23:24:12 +00:00
4566798afc iterator adaptor update and related changes
[SVN r11554]
2001-11-04 02:50:10 +00:00
10 changed files with 414 additions and 1423 deletions

View File

@ -1,159 +0,0 @@
#ifndef BOOST_ITERATOR_CATEGORIES_HPP
#define BOOST_ITERATOR_CATEGORIES_HPP
#include <boost/config.hpp>
#include <boost/type_traits/conversion_traits.hpp>
#include <boost/type_traits/cv_traits.hpp>
#include <boost/pending/ct_if.hpp>
#include <boost/detail/iterator.hpp>
namespace boost {
// Return Type Categories
struct readable_iterator_tag { };
struct writable_iterator_tag { };
struct swappable_iterator_tag { };
struct mutable_lvalue_iterator_tag :
virtual public writable_iterator_tag,
virtual public readable_iterator_tag { };
struct constant_lvalue_iterator_tag :
virtual public readable_iterator_tag { };
// Traversal Categories
struct forward_traversal_tag { };
struct bidirectional_traversal_tag : public forward_traversal_tag { };
struct random_access_traversal_tag : public bidirectional_traversal_tag { };
struct error_iterator_tag { };
// Inherit from iterator_base if your iterator defines its own
// return_category and traversal_category. Otherwise, the "old style"
// iterator category will be mapped to the return_category and
// traversal_category.
struct new_iterator_base { };
namespace detail {
struct return_category_from_nested_type {
template <typename Iterator> struct bind {
typedef typename Iterator::return_category type;
};
};
struct traversal_category_from_nested_type {
template <typename Iterator> struct bind {
typedef typename Iterator::traversal_category type;
};
};
template <typename ValueType>
struct choose_lvalue_return {
typedef typename ct_if<is_const<ValueType>::value,
boost::constant_lvalue_iterator_tag,
boost::mutable_lvalue_iterator_tag>::type type;
};
template <typename Category, typename ValueType>
struct iter_category_to_return {
typedef typename ct_if<
is_convertible<Category*, std::forward_iterator_tag*>::value,
typename choose_lvalue_return<ValueType>::type,
typename ct_if<
is_convertible<Category*, std::input_iterator_tag*>::value,
boost::readable_iterator_tag,
typename ct_if<
is_convertible<Category*, std::output_iterator_tag*>::value,
boost::writable_iterator_tag,
boost::error_iterator_tag
>::type
>::type
>::type type;
};
template <typename Category>
struct iter_category_to_traversal {
typedef typename ct_if<
is_convertible<Category*, std::random_access_iterator_tag*>::value,
random_access_traversal_tag,
typename ct_if<
is_convertible<Category*, std::bidirectional_iterator_tag*>::value,
bidirectional_traversal_tag,
forward_traversal_tag
>::type
>::type type;
};
struct return_category_from_old_traits {
template <typename Iterator> class bind {
typedef boost::detail::iterator_traits<Iterator> OldTraits;
typedef typename OldTraits::iterator_category Cat;
typedef typename OldTraits::value_type value_type;
public:
typedef iter_category_to_return<Cat, value_type>::type type;
};
};
struct traversal_category_from_old_traits {
template <typename Iterator> class bind {
typedef boost::detail::iterator_traits<Iterator> OldTraits;
typedef typename OldTraits::iterator_category Cat;
public:
typedef iter_category_to_traversal<Cat>::type type;
};
};
template <typename Iterator>
class choose_return_category {
typedef typename ct_if<is_convertible<Iterator*,
new_iterator_base*>::value,
return_category_from_nested_type,
return_category_from_old_traits>::type Choice;
public:
typedef typename Choice:: template bind<Iterator>::type type;
};
template <typename Iterator>
class choose_traversal_category {
typedef typename ct_if<is_convertible<Iterator*,
new_iterator_base*>::value,
traversal_category_from_nested_type,
traversal_category_from_old_traits>::type Choice;
public:
typedef typename Choice:: template bind<Iterator>::type type;
};
} // namespace detail
template <class Iterator>
struct return_category {
typedef typename detail::choose_return_category<Iterator>::type type;
};
template <class Iterator>
struct traversal_category {
typedef typename detail::choose_traversal_category<Iterator>::type type;
};
#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
template <typename T>
struct return_category<T*>
{
typedef typename ct_if<is_const<T>::value,
constant_lvalue_iterator_tag,
mutable_lvalue_iterator_tag>::type type;
};
template <typename T>
struct traversal_category<T*>
{
typedef random_access_traversal_tag type;
};
#endif
} // namespace boost
#endif // BOOST_ITERATOR_CATEGORIES_HPP

View File

@ -1,172 +0,0 @@
#ifndef BOOST_ITERATOR_CONCEPTS_HPP
#define BOOST_ITERATOR_CONCEPTS_HPP
#include <boost/concept_check.hpp>
#include <boost/iterator_categories.hpp>
#include <boost/type_traits/conversion_traits.hpp>
#include <boost/static_assert.hpp>
namespace boost_concepts {
// Used a different namespace here (instead of "boost") so that the
// concept descriptions do not take for granted the names in
// namespace boost.
//===========================================================================
// Iterator Access Concepts
template <typename Iterator>
class ReadableIteratorConcept {
public:
typedef typename std::iterator_traits<Iterator>::value_type value_type;
typedef typename std::iterator_traits<Iterator>::reference reference;
typedef typename boost::return_category<Iterator>::type return_category;
void constraints() {
boost::function_requires< boost::SGIAssignableConcept<Iterator> >();
boost::function_requires< boost::EqualityComparableConcept<Iterator> >();
boost::function_requires<
boost::DefaultConstructibleConcept<Iterator> >();
BOOST_STATIC_ASSERT((boost::is_convertible<return_category*,
boost::readable_iterator_tag*>::value));
reference r = *i; // or perhaps read(x)
value_type v(r);
boost::ignore_unused_variable_warning(v);
}
Iterator i;
};
template <typename Iterator, typename ValueType>
class WritableIteratorConcept {
public:
typedef typename boost::return_category<Iterator>::type return_category;
void constraints() {
boost::function_requires< boost::SGIAssignableConcept<Iterator> >();
boost::function_requires< boost::EqualityComparableConcept<Iterator> >();
boost::function_requires<
boost::DefaultConstructibleConcept<Iterator> >();
BOOST_STATIC_ASSERT((boost::is_convertible<return_category*,
boost::writable_iterator_tag*>::value));
*i = v; // a good alternative could be something like write(x, v)
}
ValueType v;
Iterator i;
};
template <typename Iterator>
class ConstantLvalueIteratorConcept {
public:
typedef typename std::iterator_traits<Iterator>::value_type value_type;
typedef typename std::iterator_traits<Iterator>::reference reference;
typedef typename boost::return_category<Iterator>::type return_category;
void constraints() {
boost::function_requires< ReadableIteratorConcept<Iterator> >();
BOOST_STATIC_ASSERT((boost::is_convertible<return_category*,
boost::constant_lvalue_iterator_tag*>::value));
BOOST_STATIC_ASSERT((boost::is_same<reference,
const value_type&>::value));
reference v = *i;
boost::ignore_unused_variable_warning(v);
}
Iterator i;
};
template <typename Iterator>
class MutableLvalueIteratorConcept {
public:
typedef typename std::iterator_traits<Iterator>::value_type value_type;
typedef typename std::iterator_traits<Iterator>::reference reference;
typedef typename boost::return_category<Iterator>::type return_category;
void constraints() {
boost::function_requires< ReadableIteratorConcept<Iterator> >();
boost::function_requires<
WritableIteratorConcept<Iterator, value_type> >();
BOOST_STATIC_ASSERT((boost::is_convertible<return_category*,
boost::mutable_lvalue_iterator_tag*>::value));
BOOST_STATIC_ASSERT((boost::is_same<reference, value_type&>::value));
reference v = *i;
boost::ignore_unused_variable_warning(v);
}
Iterator i;
};
//===========================================================================
// Iterator Traversal Concepts
template <typename Iterator>
class ForwardIteratorConcept {
public:
typedef typename boost::traversal_category<Iterator>::type traversal_category;
void constraints() {
boost::function_requires< boost::SGIAssignableConcept<Iterator> >();
boost::function_requires< boost::EqualityComparableConcept<Iterator> >();
boost::function_requires<
boost::DefaultConstructibleConcept<Iterator> >();
BOOST_STATIC_ASSERT((boost::is_convertible<traversal_category*,
boost::forward_traversal_tag*>::value));
++i;
(void)i++;
}
Iterator i;
};
template <typename Iterator>
class BidirectionalIteratorConcept {
public:
typedef typename boost::traversal_category<Iterator>::type traversal_category;
void constraints() {
boost::function_requires< ForwardIteratorConcept<Iterator> >();
BOOST_STATIC_ASSERT((boost::is_convertible<traversal_category*,
boost::bidirectional_traversal_tag*>::value));
--i;
(void)i--;
}
Iterator i;
};
template <typename Iterator>
class RandomAccessIteratorConcept {
public:
typedef typename boost::traversal_category<Iterator>::type traversal_category;
typedef typename std::iterator_traits<Iterator>::difference_type
difference_type;
void constraints() {
boost::function_requires< BidirectionalIteratorConcept<Iterator> >();
BOOST_STATIC_ASSERT((boost::is_convertible<traversal_category*,
boost::random_access_traversal_tag*>::value));
i += n;
i = i + n;
i = n + i;
i -= n;
i = i - n;
n = i - j;
}
difference_type n;
Iterator i, j;
};
} // namespace boost_concepts
#endif // BOOST_ITERATOR_CONCEPTS_HPP

View File

@ -1,73 +0,0 @@
#include <boost/iterator_concepts.hpp>
#include <boost/operators.hpp>
struct new_iterator
: public boost::iterator<std::random_access_iterator_tag, int>,
public boost::new_iterator_base
{
typedef boost::random_access_traversal_tag traversal_category;
typedef boost::mutable_lvalue_iterator_tag return_category;
int& operator*() const { return *m_x; }
new_iterator& operator++() { return *this; }
new_iterator operator++(int) { return *this; }
new_iterator& operator--() { return *this; }
new_iterator operator--(int) { return *this; }
new_iterator& operator+=(std::ptrdiff_t) { return *this; }
new_iterator operator+(std::ptrdiff_t) { return *this; }
new_iterator& operator-=(std::ptrdiff_t) { return *this; }
std::ptrdiff_t operator-(const new_iterator&) const { return 0; }
new_iterator operator-(std::ptrdiff_t) const { return *this; }
bool operator==(const new_iterator&) const { return false; }
bool operator!=(const new_iterator&) const { return false; }
bool operator<(const new_iterator&) const { return false; }
int* m_x;
};
new_iterator operator+(std::ptrdiff_t, new_iterator x) { return x; }
struct old_iterator
: public boost::iterator<std::random_access_iterator_tag, int>
{
int& operator*() const { return *m_x; }
old_iterator& operator++() { return *this; }
old_iterator operator++(int) { return *this; }
old_iterator& operator--() { return *this; }
old_iterator operator--(int) { return *this; }
old_iterator& operator+=(std::ptrdiff_t) { return *this; }
old_iterator operator+(std::ptrdiff_t) { return *this; }
old_iterator& operator-=(std::ptrdiff_t) { return *this; }
old_iterator operator-(std::ptrdiff_t) const { return *this; }
std::ptrdiff_t operator-(const old_iterator&) const { return 0; }
bool operator==(const old_iterator&) const { return false; }
bool operator!=(const old_iterator&) const { return false; }
bool operator<(const old_iterator&) const { return false; }
int* m_x;
};
old_iterator operator+(std::ptrdiff_t, old_iterator x) { return x; }
int
main()
{
#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
boost::function_requires<
boost_concepts::MutableLvalueIteratorConcept<int*> >();
boost::function_requires<
boost_concepts::RandomAccessIteratorConcept<int*> >();
boost::function_requires<
boost_concepts::ConstantLvalueIteratorConcept<const int*> >();
boost::function_requires<
boost_concepts::RandomAccessIteratorConcept<const int*> >();
#endif
boost::function_requires<
boost_concepts::MutableLvalueIteratorConcept<new_iterator> >();
boost::function_requires<
boost_concepts::RandomAccessIteratorConcept<new_iterator> >();
boost::function_requires<
boost_concepts::MutableLvalueIteratorConcept<old_iterator> >();
boost::function_requires<
boost_concepts::RandomAccessIteratorConcept<old_iterator> >();
return 0;
}

View File

@ -1,160 +0,0 @@
<html>
<!--
-- Copyright (c) Jeremy Siek 2000,2001
--
-- Permission to use, copy, modify, distribute and sell this software
-- and its documentation for any purpose is hereby granted without fee,
-- provided that the above copyright notice appears in all copies and
-- that both that copyright notice and this permission notice appear
-- in supporting documentation. I make no representations about the
-- suitability of this software for any purpose. It is provided "as is"
-- without express or implied warranty.
-->
<head>
<title>Boost Iterator Traits</title>
</head>
<BODY BGCOLOR="#ffffff" LINK="#0000ee" TEXT="#000000" VLINK="#551a8b"
ALINK="#ff0000">
<IMG SRC="../../../../c++boost.gif"
ALT="C++ Boost" width="277" height="86">
<BR Clear>
<h1>Boost Iterator Category Traits</h1>
Header <tt><a href="../../boost/iterator_categories.hpp">boost/iterator_categories.hpp</a></tt>
<p>
The <tt>boost::traversal_category</tt> and
<tt>boost::return_category</tt> traits classes provides access to the
category tags for iterators that model the Boost <a
href="./iterator_concepts.htm">Iterator Concepts</a>, which are a
replacement for the iterator requirements in the C++ standard. The
other associated types of the Boost iterator concepts are accessed
through the <tt>std::iterator_traits</tt> class.
<ul>
<li><tt>traversal_category&lt;Iter&gt;::type</tt>&nbsp;&nbsp; Can the iterator go forward, backward, etc.?
<li><tt>return_category&lt;Iter&gt;::type</tt>&nbsp;&nbsp; Is the iterator read or write only?
Is the dereferenced type an lvalue?
</ul>
<p>
An important feature of the <tt>boost::traversal_category</tt> and
<tt>boost::return_category</tt> classes is that they are <b>backwards
compatible</b>, i.e., they automatically work for iterators for which
there are valid definitions of <tt>std::iterator_traits</tt>. The old
<tt>iterator_category</tt> is mapped to the appropriate traversal and
return categories.
<p>
When creating a new iterator type that is meant to work with
<tt>boost::traversal_category</tt> and
<tt>boost::return_category</tt>, you can either create a
specialization of these classes for your iterator type, or you can
provide all the necessary associated types as nested typedefs. In
this case, your iterator class will need to inherit from
<tt>new_iterator_base</tt> to let the category traits know
that it will be able to find typedefs for <tt>traversal_category</tt>
and <tt>return_category</tt> in you iterator class.
Each of the new iterator requirements will need a category tag.
<pre>
namespace boost {
// Return Type Categories
struct readable_iterator_tag { };
struct writable_iterator_tag { };
struct swappable_iterator_tag { };
struct mutable_lvalue_iterator_tag : virtual public writable_iterator_tag,
virtual public readable_iterator_tag { };
struct constant_lvalue_iterator_tag : public readable_iterator_tag { };
// Traversal Categories
struct forward_traversal_tag { };
struct bidirectional_traversal_tag : public forward_traversal_tag { };
struct random_access_traversal_tag : public bidirectional_traversal_tag { };
}
</pre>
<p>
The following is pseudo-code for the iterator category traits classes.
<pre>
namespace boost {
<i>// Inherit from iterator_base if your iterator defines its own
// return_category and traversal_category. Otherwise, the "old style"
// iterator category will be mapped to the return_category and
// traversal_category.</i>
struct new_iterator_base { };
template &lt;typename Iterator&gt;
struct return_category
{
<b><i>// Pseudo-code</i></b>
if (Iterator inherits from new_iterator_base) {
typedef typename Iterator::return_category type;
} else {
typedef std::iterator_traits&lt;Iterator&gt; OldTraits;
typedef typename OldTraits::iterator_category Cat;
if (Cat inherits from std::forward_iterator_tag)
if (is-const(T))
typedef boost::constant_lvalue_iterator_tag type;
else
typedef boost::mutable_lvalue_iterator_tag type;
else if (Cat inherits from std::input_iterator_tag)
typedef boost::readable_iterator_tag type;
else if (Cat inherits from std::output_iterator_tag)
typedef boost::writable_iterator_tag type;
}
};
template &lt;typename T&gt;
struct return_category&lt;T*&gt;
{
<b><i>// Pseudo-code</i></b>
if (is-const(T))
typedef boost::constant_lvalue_iterator_tag type;
else
typedef boost::mutable_lvalue_iterator_tag type;
};
template &lt;typename Iterator&gt;
struct traversal_category
{
<b><i>// Pseudo-code</i></b>
if (Iterator inherits from new_iterator_base) {
typedef typename Iterator::traversal_category type;
} else {
typedef std::iterator_traits&lt;Iterator&gt; OldTraits;
typedef typename OldTraits::iterator_category Cat;
if (Cat inherits from std::random_access_iterator_tag)
typedef boost::random_access_traversal_tag type;
else if (Cat inherits from std::bidirectional_iterator_tag)
typedef boost::bidirectional_traversal_tag type;
else if (Cat inherits from std::forward_iterator_tag)
typedef boost::forward_traversal_tag type;
}
};
template &lt;typename T&gt;
struct traversal_category&lt;T*&gt;
{
typedef boost::random_access_traversal_tag type;
};
}
</pre>
<hr>
<address><a href="mailto:jsiek@lsc.nd.edu">jeremy siek</a></address>
<!-- Created: Sun Mar 18 14:06:57 EST 2001 -->
<!-- hhmts start -->
Last modified: Mon Mar 19 12:59:30 EST 2001
<!-- hhmts end -->
</body>
</html>

View File

@ -1,37 +0,0 @@
#FIG 3.2
Landscape
Center
Inches
Letter
100.00
Single
-2
1200 2
6 150 2325 4275 4350
2 1 0 1 0 7 100 0 -1 4.000 0 0 -1 1 0 2
1 1 1.00 60.00 120.00
1725 4050 1725 3450
2 1 0 1 0 7 100 0 -1 4.000 0 0 -1 1 0 2
1 1 1.00 60.00 120.00
1725 3150 1725 2550
4 0 0 100 0 19 18 0.0000 4 210 3180 375 2550 ForwardTraversalIterator\001
4 0 0 100 0 19 18 0.0000 4 210 3765 225 3450 BidirectionalTraversalIterator\001
4 0 0 100 0 19 18 0.0000 4 210 4125 150 4350 RandomAccessTraversalIterator\001
-6
2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 1 0 2
1 1 1.00 60.00 120.00
4800 3600 4800 2400
2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 1 0 2
1 1 1.00 60.00 120.00
6900 3000 5400 2400
2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 1 0 2
1 1 1.00 60.00 120.00
6900 3000 7500 2400
2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 1 0 2
1 1 1.00 60.00 120.00
6900 3000 9075 2475
4 0 0 100 0 19 18 0.0000 4 210 2040 6600 2400 WritableIterator\001
4 0 0 100 0 19 18 0.0000 4 210 2145 3900 2400 ReadableIterator\001
4 0 0 50 0 19 18 0.0000 4 210 2835 5700 3300 MutableLvalueIterator\001
4 0 0 50 0 19 18 0.0000 4 270 2355 9075 2400 SwappableIterator\001
4 0 0 50 0 19 18 0.0000 4 210 2970 3825 3900 ConstantLvalueIterator\001

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.2 KiB

View File

@ -1,663 +0,0 @@
<HTML>
<!--
-- Copyright (c) Jeremy Siek 2000
--
-- Permission to use, copy, modify, distribute and sell this software
-- and its documentation for any purpose is hereby granted without fee,
-- provided that the above copyright notice appears in all copies and
-- that both that copyright notice and this permission notice appear
-- in supporting documentation. I make no representations about the
-- suitability of this software for any purpose. It is provided "as is"
-- without express or implied warranty.
-->
<!--
-- Copyright (c) 1996-1999
-- Silicon Graphics Computer Systems, Inc.
--
-- Permission to use, copy, modify, distribute and sell this software
-- and its documentation for any purpose is hereby granted without fee,
-- provided that the above copyright notice appears in all copies and
-- that both that copyright notice and this permission notice appear
-- in supporting documentation. Silicon Graphics makes no
-- representations about the suitability of this software for any
-- purpose. It is provided "as is" without express or implied warranty.
--
-- Copyright (c) 1994
-- Hewlett-Packard Company
--
-- Permission to use, copy, modify, distribute and sell this software
-- and its documentation for any purpose is hereby granted without fee,
-- provided that the above copyright notice appears in all copies and
-- that both that copyright notice and this permission notice appear
-- in supporting documentation. Hewlett-Packard Company makes no
-- representations about the suitability of this software for any
-- purpose. It is provided "as is" without express or implied warranty.
--
-->
<Head>
<Title>Iterator Concepts</Title>
<BODY BGCOLOR="#ffffff" LINK="#0000ee" TEXT="#000000" VLINK="#551a8b"
ALINK="#ff0000">
<IMG SRC="../../../../c++boost.gif"
ALT="C++ Boost" width="277" height="86">
<BR Clear>
<h1>Iterator Concepts</h1>
<p>The standard iterator categories and requirements are flawed because
they use a single hierarchy of requirements to address two orthogonal
issues: <b><i>iterator traversal</i></b> and <b><i>dereference return
type</i></b>. The current iterator requirement hierarchy is mainly
geared towards iterator traversal (hence the category names), while
requirements that address dereference return type sneak in at various
places.
<p>
The iterator requirements should be separated into two hierarchies.
One set of concepts handles the return type semantics:
<ul>
<li><a href="#concept:ReadableIterator">Readable Iterator</a></li>
<li><a href="#concept:WritableIterator">Writable Iterator</a></li>
<li><a href="#concept:SwappableIterator">Swappable Iterator</a></li>
<li><a href="#concept:ConstantLvalueIterator">Constant Lvalue Iterator</a></li>
<li><a href="#concept:MutableLvalueIterator">Mutable Lvalue Iterator</a></li>
</ul>
The other set of concepts handles iterator traversal:
<ul>
<li><a href="#concept:ForwardTraversalIterator">Forward Traversal Iterator</a></li>
<li><a href="#concept:BidirectionalTraversalIterator">Bidirectional Traversal Iterator</a></li>
<li><a href="#concept:RandomAccessTraversalIterator">Random Access Traversal Iterator</a></li>
</ul>
The current Input Iterator and Output Iterator requirements will
continue to be used as is. Note that Input Iterator implies Readable
Iterator and Output Iterator implies Writable Iterator.
<p>
Note: we considered defining a Single-Pass Iterator, which could be
combined with Readable or Writable Iterator to replace the Input and
Output Iterator requirements. We rejected this idea because there are
some differences between Input and Output Iterators that make it hard
to merge them: for example Input Iterator requires Equality Comparable
while Output Iterator does not.
<p></p>
<DIV ALIGN="CENTER"><A NAME="fig:graph-concepts"></A></A>
<TABLE>
<CAPTION ALIGN="TOP"><STRONG>Figure 1:</STRONG>
The iterator concepts and refinement relationships.
</CAPTION>
<TR><TD><IMG SRC="./iterator_concepts.gif" ></TD></TR>
</TABLE>
</DIV>
<p></p>
<h2>Relationship with the standard iterator concepts</h2>
<p>
std::Input Iterator implies boost::ReadableIterator.
<p>
std::Output Iterator implies boost::Writable Iterator.
<p>
std::Forward Iterator refines boost::Forward Iterator and
boost::Constant Lvalue Iterator or boost::Mutable Lvalue Iterator.
<p>
std::Bidirectional Iterator refines boost::Bidirectional Iterator and
boost::Constant Lvalue Iterator or boost::Mutable Lvalue Iterator.
<p>
std::Random Access Iterator refines boost::Random Access Iterator and
boost::Constant Lvalue Iterator or boost::Mutable Lvalue Iterator.
<h3>Notation</h3>
<Table>
<tr>
<td><tt>X</tt></td>
<td>The iterator type.</td>
</tr>
<tr>
<td><tt>T</tt></td>
<td>The value type of <tt>X</tt>, i.e., <tt>std::iterator_traits&lt;X&gt;::value_type</tt>.</td>
</tr>
<tr>
<td><tt>x</tt>, <tt>y</tt></td>
<td>An object of type <tt>X</tt>.</td>
</tr>
<tr>
<td><tt>t</tt></td>
<td>An object of type <tt>T</tt>.</td>
</tr>
</table>
<p>
<hr>
<!--------------------------------------------------------------------------->
<H3><A NAME="concept:ReadableIterator"></A>
Readable Iterator
</H3>
A Readable Iterator is an iterator that dereferences to produce an
rvalue that is convertible to the <tt>value_type</tt> of the
iterator.
<h3>Associated Types</h3>
<Table border>
<tr>
<td>Value type</td>
<td><tt>std::iterator_traits&lt;X&gt;::value_type</tt></td>
<td>The type of the objects pointed to by the iterator.</td>
</tr>
<tr>
<td>Reference type</td>
<td><tt>std::iterator_traits&lt;X&gt;::reference</tt></td>
<td>
The return type of dereferencing the iterator. This
type must be convertible to <tt>T</tt>.
</td>
</tr>
<tr>
<td>Return Category</td>
<td><tt>std::return_category&lt;X&gt;::type</tt></td>
<td>
A type convertible to <tt>std::readable_iterator_tag</tt>
</td>
</tr>
</Table>
<h3>Refinement of</h3>
<A href="http://www.boost.org/libs/utility/CopyConstructible.html">Copy Constructible</A>
<h3>Valid expressions</h3>
<Table border>
<tr><TH>Name</TH><TH>Expression</TH><TH>Type requirements</TH><TH>Return type</TH></tr>
<tr>
<td>Dereference</td>
<td><tt>*x</tt></td>
<td>&nbsp;</td>
<td><tt>std::iterator_traits&lt;X&gt;::reference</tt></td>
</tr>
<tr>
<td>Member access</td>
<td><tt>x-&gt;m</tt></td>
<td><tt>T</tt> is a type with a member named <tt>m</tt>.</td>
<td>
If <tt>m</tt> is a data member, the type of <tt>m</tt>.
If <tt>m</tt> is a member function, the return type of <tt>m</tt>.
</td>
</tr>
</table>
<p>
<hr>
<!--------------------------------------------------------------------------->
<H3><A NAME="concept:WritableIterator"></A>
Writable Iterator
</H3>
A Writable Iterator is an iterator that can be used to store a value
using the dereference-assignment expression.
<h3>Definitions</h3>
If <tt>x</tt> is an Writable Iterator of type <tt>X</tt>, then the
expression <tt>*x = a;</tt> stores the value <tt>a</tt> into
<tt>x</tt>. Note that <tt>operator=</tt>, like other C++ functions,
may be overloaded; it may, in fact, even be a template function. In
general, then, <tt>a</tt> may be any of several different types. A
type <tt>A</tt> belongs to the <i>set of value types</i> of <tt>X</tt>
if, for an object <tt>a</tt> of type <tt>A</tt>, <tt>*x = a;</tt> is
well-defined and does not require performing any non-trivial
conversions on <tt>a</tt>.
<h3>Associated Types</h3>
<Table border>
<tr>
<td>Return Category</td>
<td><tt>std::return_category&lt;X&gt;::type</tt></td>
<td>
A type convertible to <tt>std::writable_iterator_tag</tt>
</td>
</tr>
</Table>
<h3>Refinement of</h3>
<A href="http://www.boost.org/libs/utility/CopyConstructible.html">Copy Constructible</A>
<h3>Valid expressions</h3>
<Table border>
<tr>
<TH>Name</TH><TH>Expression</TH><TH>Return type</TH>
</tr>
<tr>
<td>Dereference assignment</td>
<td><tt>*x = a</tt></td>
<td>unspecified</td>
</tr>
</table>
<p>
<hr>
<!--------------------------------------------------------------------------->
<H3><A NAME="concept:SwappableIterator"></A>
Swappable Iterator
</H3>
A Swappable Iterator is an iterator whose dereferenced values can be
swapped.
<p>
Note: the requirements for Swappable Iterator are dependent on the
issues surrounding <tt>std::swap()</tt> being resolved. Here we assume
that the issue will be resolved by allowing the overload of
<tt>std::swap()</tt> for user-defined types.
<p>
Note: Readable Iterator and Writable Iterator combined implies
Swappable Iterator because of the fully templated
<tt>std::swap()</tt>. However, Swappable Iterator does not imply
Readable Iterator nor Writable Iterator.
<h3>Associated Types</h3>
<Table border>
<tr>
<td>Return Category</td>
<td><tt>std::return_category&lt;X&gt;::type</tt></td>
<td>
A type convertible to <tt>std::swappable_iterator_tag</tt>
</td>
</tr>
</Table>
<h3>Valid expressions</h3>
Of the two valid expressions listed below, only one <b>OR</b> the
other is required. If <tt>std::iter_swap()</tt> is overloaded for
<tt>X</tt> then <tt>std::swap()</tt> is not required. If
<tt>std::iter_swap()</tt> is not overloaded for <tt>X</tt> then the
default (fully templated) version is used, which will call
<tt>std::swap()</tt> (this means changing the current requirements for
<tt>std::iter_swap()</tt>).
<p>
<Table border>
<tr>
<TH>Name</TH><TH>Expression</TH><TH>Return type</TH>
</tr>
<tr>
<td>Iterator Swap</td>
<td><tt>std::iter_swap(x, y)</tt></td>
<td>void</td>
</tr>
<tr>
<td>Dereference and Swap</td>
<td><tt>std::swap(*x, *y)</tt></td>
<td>void</td>
</tr>
</table>
<p>
<hr>
<!--------------------------------------------------------------------------->
<H3><A NAME="concept:ConstantLvalueIterator"></A>
Constant Lvalue Iterator
</H3>
A Constant Lvalue Iterator is an iterator that dereferences to produce a
const reference to the pointed-to object, i.e., the associated
<tt>reference</tt> type is <tt>const T&amp;</tt>. Changing the value
of or destroying an iterator that models Constant Lvalue Iterator does
not invalidate pointers and references previously obtained from that
iterator.
<h3>Refinement of</h3>
<a href="#concept:ReadableIterator">Readable Iterator</a>
<h3>Associated Types</h3>
<Table border>
<tr>
<td>Reference type</td>
<td><tt>std::iterator_traits&lt;X&gt;::reference</tt></td>
<td>
The return type of dereferencing the iterator, which must be
<tt>const T&amp;</tt>.
</td>
</tr>
<!-- I don't think this is needed
<tr>
<td>Pointer type</td>
<td><tt>std::iterator_traits&lt;X&gt;::pointer</tt></td>
<td>
The pointer to the value type, which must be <tt>const T*</tt>.
</td>
</tr>
-->
<tr>
<td>Return Category</td>
<td><tt>std::return_category&lt;X&gt;::type</tt></td>
<td>
A type convertible to <tt>std::constant_lvalue_iterator_tag</tt>
</td>
</tr>
</table>
<!-- these are not necessary now that we use reference as operator* return type
<h3>Valid expressions</h3>
<Table border>
<tr><TH>Name</TH><TH>Expression</TH><TH>Type requirements</TH><TH>Return type</TH></tr>
<tr>
<td>Dereference</td>
<td><tt>*x</tt></td>
<td>&nbsp;</td>
<td><tt>std::iterator_traits&lt;X&gt;::reference</tt></td>
</tr>
<tr>
<td>Member access</td>
<td><tt>x-&gt;m</tt></td>
<td><tt>T</tt> is a type with a member named <tt>m</tt>.</td>
<td>
&nbsp;
</td>
</tr>
</table>
-->
<p>
<hr>
<!--------------------------------------------------------------------------->
<H3><A NAME="concept:MutableLvalueIterator"></A>
Mutable Lvalue Iterator
</H3>
A Mutable Lvalue Iterator is an iterator that dereferences to produce a
reference to the pointed-to object. The associated <tt>reference</tt>
type is <tt>T&amp;</tt>. Changing the value of or destroying an
iterator that models Mutable Lvalue Iterator does not invalidate
pointers and references previously obtained from that iterator.
<h3>Refinement of</h3>
<a href="#concept:ReadableIterator">Readable Iterator</a>,
<a href="#concept:WritableIterator">Writable Iterator</a>,
and <a href="#concept:SwappableIterator">Swappable Iterator</a>.
<h3>Associated Types</h3>
<Table border>
<tr>
<td>Reference type</td>
<td><tt>std::iterator_traits&lt;X&gt;::reference</tt></td>
<td>The return type of dereferencing the iterator, which must be
<tt>T&amp;</tt>.</td>
</tr>
<!-- I don't think this is necessary
<tr>
<td>Pointer type</td>
<td><tt>std::iterator_traits&lt;X&gt;::pointer</tt></td>
<td>
The pointer to the value type, which is <tt>T*</tt>.
</td>
</tr>
-->
<tr>
<td>Return Category</td>
<td><tt>std::return_category&lt;X&gt;::type</tt></td>
<td>
A type convertible to <tt>std::mutable_lvalue_iterator_tag</tt>
</td>
</tr>
</table>
<!-- no longer needed since the return type is specified as reference in the readable iterator
<h3>Valid expressions</h3>
<Table border>
<tr><TH>Name</TH><TH>Expression</TH><TH>Type requirements</TH><TH>Return type</TH></tr>
<tr>
<td>Dereference</td>
<td><tt>*x</tt></td>
<td>&nbsp;</td>
<td><tt>std::iterator_traits&lt;X&gt;::reference</tt></td>
</tr>
<tr>
<td>Member access</td>
<td><tt>x-&gt;m</tt></td>
<td><tt>T</tt> is a type with a member named <tt>m</tt>.</td>
<td>
&nbsp;
</td>
</tr>
</table>
-->
<p>
<hr>
<!--------------------------------------------------------------------------->
<H3><A NAME="concept:ForwardTraversalIterator"></A>
Forward Traversal Iterator
</H3>
The Forward Iterator is an iterator that can be incremented. Also, it
is permissible to make multiple passes through the iterator's range.
<h3>Refinement of</h3>
<A href="http://www.boost.org/libs/utility/CopyConstructible.html">Copy Constructible</A>,
<A href="http://www.boost.org/libs/utility/Assignable.html">Assignable</A>,
<A href="http://www.sgi.com/tech/stl/DefaultConstructible.html">Default Constructible</A>, and
<A href="http://www.sgi.com/tech/stl/EqualityComparable.html">Equality Comparable</A>
<h3>Associated types</h3>
<Table border>
<tr>
<td>Difference Type</td>
<td><tt>std::iterator_traits&lt;X&gt;::difference_type</tt></td>
<td>
A signed integral type used for representing distances
between iterators that point into the same range.
</td>
</tr>
<tr>
<td>Traversal Category</td>
<td><tt>std::traversal_category&lt;X&gt;::type</tt></td>
<td>
A type convertible to <tt>std::forward_traversal_tag</tt>
</td>
</tr>
</Table>
<h3>Valid expressions</h3>
<Table border>
<tr>
<TH>Name</TH><TH>Expression</TH><TH>Type requirements</TH>
<TH>Return type</TH>
</tr>
<tr>
<td>Preincrement</td>
<td><tt>++i</tt></td><td>&nbsp;</td><td><tt>X&amp;</tt></td>
</tr>
<tr>
<td>Postincrement</td>
<td><tt>i++</tt></td><td>&nbsp;</td><td>convertible to <tt>const X&amp;</tt></td>
</tr>
</Table>
<p>
<hr>
<!--------------------------------------------------------------------------->
<H3><A NAME="concept:BidirectionalTraversalIterator"></A>
Bidirectional Traversal Iterator
</H3>
An iterator that can be incremented and decremented.
<h3>Refinement of</h3>
<a href="#concept:ForwardTraversalIterator">Forward Traversal Iterator</a>
<h3>Associated types</h3>
<Table border>
<tr>
<td>Traversal Category</td>
<td><tt>std::traversal_category&lt;X&gt;::type</tt></td>
<td>
A type convertible to <tt>std::bidirectional_traversal_tag</tt>
</td>
</tr>
</Table>
<h3>Valid expressions</h3>
<Table border>
<tr>
<TH>Name</TH><TH>Expression</TH><TH>Type requirements</TH>
<TH>Return type</TH>
</tr>
<tr><td>Predecrement</td>
<td><tt>--i</tt></td><td>&nbsp;</td><td><tt>X&amp;</tt></td>
</tr>
<tr><td>Postdecrement</td>
<td><tt>i--</tt></td><td>&nbsp;</td><td>convertible to <tt>const X&amp;</tt></td>
</tr>
</table>
<p>
<hr>
<!--------------------------------------------------------------------------->
<H3><A NAME="concept:RandomAccessTraversalIterator"></A>
Random Access Traversal Iterator
</H3>
An iterator that provides constant-time methods for moving forward and
backward in arbitrary-sized steps.
<h3>Refinement of</h3>
<a href="#concept:BidirectionalTraversalIterator">Bidirectional Traversal Iterator</a> and
<A href="http://www.sgi.com/tech/stl/LessThanComparable.html">Less Than Comparable</A> where <tt>&lt;</tt> is a total ordering
<h3>Associated types</h3>
<Table border>
<tr>
<td>Traversal Category</td>
<td><tt>std::traversal_category&lt;X&gt;::type</tt></td>
<td>
A type convertible to <tt>std::random_access_traversal_tag</tt>
</td>
</tr>
</Table>
<h3>Valid expressions</h3>
<Table border>
<tr><TH>Name</TH><TH>Expression</TH><TH>Type requirements</TH>
<TH>Return type</TH>
</tr>
<tr><td>Iterator addition</td>
<td><tt>i += n</tt></td><td>&nbsp;</td><td><tt>X&amp;</tt></td>
</tr>
<tr><td>Iterator addition</td>
<td><tt>i + n</tt> or <tt>n + i</tt></td><td>&nbsp;</td><td><tt>X</tt></td>
</tr>
<tr><td>Iterator subtraction</td>
<td><tt>i -= n</tt></td><td>&nbsp;</td><td><tt>X&amp;</tt></td>
</tr>
<tr><td>Iterator subtraction</td>
<td><tt>i - n</tt></td><td>&nbsp;</td><td><tt>X</tt></td>
</tr>
<tr><td>Difference</td>
<td><tt>i - j</tt></td><td>&nbsp;</td><td><tt>std::iterator_traits&lt;X&gt;::difference_type</tt></td>
</tr>
<tr><td>Element operator</td>
<td><tt>i[n]</tt></td>
<td><tt>X</tt> must also be a model of
<a href="#concept:ReadableIterator">Readable Iterator</a>. </td>
<td><tt>std::iterator_traits&lt;X&gt;::reference</tt></td>
</tr>
<tr><td>Element assignment</td>
<td><tt>i[n] = t</tt></td>
<td><tt>X</tt> must also be a model of
<a href="#concept:WritableIterator">Writable Iterator</a>.</td>
<td>unspecified</td>
</tr>
</table>
<p>
<HR>
<TABLE>
<TR valign=top>
<TD nowrap>Copyright &copy 2000</TD><TD>
<A HREF="../../../../people/jeremy_siek.htm">Jeremy Siek</A>, Univ.of Notre Dame (<A HREF="mailto:jsiek@lsc.nd.edu">jsiek@lsc.nd.edu</A>)
</TD></TR></TABLE>
</body>
</html>

View File

@ -135,7 +135,15 @@ namespace detail {
// For a while, this wasn't true, but we rely on it below. This is a regression assert.
BOOST_STATIC_ASSERT(::boost::is_integral<char>::value);
# ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
BOOST_STATIC_CONSTANT(bool, value = std::numeric_limits<T>::is_specialized);
# if defined(ULLONG_MAX) || defined(ULONG_LONG_MAX)
BOOST_STATIC_CONSTANT(bool,
value = (
std::numeric_limits<T>::is_specialized
| boost::is_same<T,long long>::value
| boost::is_same<T,unsigned long long>::value));
# else
BOOST_STATIC_CONSTANT(bool, value = std::numeric_limits<T>::is_specialized);
# endif
# else
# if !defined(__BORLANDC__)
BOOST_STATIC_CONSTANT(bool, value = (
@ -173,14 +181,17 @@ struct counting_iterator_traits {
template <class Incrementable>
struct counting_iterator_policies : public default_iterator_policies
{
const Incrementable& dereference(type<const Incrementable&>, const Incrementable& i) const
{ return i; }
template <class Difference, class Iterator1, class Iterator2>
Difference distance(type<Difference>, const Iterator1& x,
const Iterator2& y) const
template <class IteratorAdaptor>
typename IteratorAdaptor::reference dereference(const IteratorAdaptor& i) const
{ return i.base(); }
template <class Iterator1, class Iterator2>
typename Iterator1::difference_type distance(
const Iterator1& x, const Iterator2& y) const
{
return boost::detail::any_distance<Difference>(x, y);//,(Difference*)());
typedef typename Iterator1::difference_type difference_type;
return boost::detail::any_distance<difference_type>(
x.base(), y.base());
}
};

View File

@ -12,6 +12,8 @@
//
// Revision History:
// 03 Nov 2001 Jeremy Siek
// Changed the named template parameter interface and internal.
// 04 Oct 2001 Jeremy Siek
// Changed projection_iterator to not rely on the default reference,
// working around a limitation of detail::iterator_traits.
@ -114,7 +116,6 @@
# include <boost/type_traits.hpp>
# include <boost/detail/iterator.hpp>
# include <boost/detail/select_type.hpp>
# include <boost/detail/named_template_params.hpp>
// I was having some problems with VC6. I couldn't tell whether our hack for
// stock GCC was causing problems so I needed an easy way to turn it on and
@ -146,7 +147,7 @@ struct TrivialIteratorPoliciesConcept
const_constraints();
}
void const_constraints() const {
Reference r = p.dereference(type<Reference>(), x);
Reference r = p.dereference(x);
b = p.equal(x, x);
ignore_unused_variable_warning(r);
}
@ -208,8 +209,7 @@ struct RandomAccessIteratorPoliciesConcept
ignore_unused_variable_warning(t);
}
void const_constraints() const {
n = p.distance(type<DifferenceType>(), x, x);
b = p.less(x, x);
n = p.distance(x, x);
}
Policies p;
Adapted x;
@ -231,37 +231,30 @@ struct default_iterator_policies
void initialize(Base&)
{ }
// The "type<Reference>" parameter is a portable mechanism for
// the iterator_adaptor class to tell this member function what
// the Reference type is, which is needed for the return type.
template <class Reference, class Base>
Reference dereference(type<Reference>, const Base& x) const
{ return *x; }
template <class IteratorAdaptor>
typename IteratorAdaptor::reference dereference(const IteratorAdaptor& x) const
{ return *x.base(); }
template <class Base>
void increment(Base& x)
{ ++x; }
template <class IteratorAdaptor>
void increment(IteratorAdaptor& x)
{ ++x.base(); }
template <class Base>
void decrement(Base& x)
{ --x; }
template <class IteratorAdaptor>
void decrement(IteratorAdaptor& x)
{ --x.base(); }
template <class Base, class DifferenceType>
void advance(Base& x, DifferenceType n)
{ x += n; }
template <class IteratorAdaptor, class DifferenceType>
void advance(IteratorAdaptor& x, DifferenceType n)
{ x.base() += n; }
template <class Difference, class Iterator1, class Iterator2>
Difference distance(type<Difference>, const Iterator1& x,
const Iterator2& y) const
{ return y - x; }
template <class IteratorAdaptor1, class IteratorAdaptor2>
typename IteratorAdaptor1::difference_type
distance(const IteratorAdaptor1& x, const IteratorAdaptor2& y) const
{ return y.base() - x.base(); }
template <class Iterator1, class Iterator2>
bool equal(const Iterator1& x, const Iterator2& y) const
{ return x == y; }
template <class Iterator1, class Iterator2>
bool less(const Iterator1& x, const Iterator2& y) const
{ return x < y; }
template <class IteratorAdaptor1, class IteratorAdaptor2>
bool equal(const IteratorAdaptor1& x, const IteratorAdaptor2& y) const
{ return x.base() == y.base(); }
};
// putting the comparisons in a base class avoids the g++
@ -277,7 +270,7 @@ inline bool operator==(const iterator_comparisons<D1,Base1>& xb,
{
const D1& x = static_cast<const D1&>(xb);
const D2& y = static_cast<const D2&>(yb);
return x.policies().equal(x.iter(), y.iter());
return x.policies().equal(x, y);
}
template <class D1, class D2, class Base1, class Base2>
@ -286,7 +279,7 @@ inline bool operator!=(const iterator_comparisons<D1,Base1>& xb,
{
const D1& x = static_cast<const D1&>(xb);
const D2& y = static_cast<const D2&>(yb);
return !x.policies().equal(x.iter(), y.iter());
return !x.policies().equal(x, y);
}
template <class D1, class D2, class Base1, class Base2>
@ -295,7 +288,7 @@ inline bool operator<(const iterator_comparisons<D1,Base1>& xb,
{
const D1& x = static_cast<const D1&>(xb);
const D2& y = static_cast<const D2&>(yb);
return x.policies().less(x.iter(), y.iter());
return x.policies().distance(y, x) < 0;
}
template <class D1, class D2, class Base1, class Base2>
@ -304,7 +297,7 @@ inline bool operator>(const iterator_comparisons<D1,Base1>& xb,
{
const D1& x = static_cast<const D1&>(xb);
const D2& y = static_cast<const D2&>(yb);
return x.policies().less(y.iter(), x.iter());
return x.policies().distance(y, x) > 0;
}
template <class D1, class D2, class Base1, class Base2>
@ -313,7 +306,7 @@ inline bool operator>=(const iterator_comparisons<D1,Base1>& xb,
{
const D1& x = static_cast<const D1&>(xb);
const D2& y = static_cast<const D2&>(yb);
return !x.policies().less(x.iter(), y.iter());
return x.policies().distance(y, x) >= 0;
}
template <class D1, class D2, class Base1, class Base2>
@ -322,7 +315,7 @@ inline bool operator<=(const iterator_comparisons<D1,Base1>& xb,
{
const D1& x = static_cast<const D1&>(xb);
const D2& y = static_cast<const D2&>(yb);
return !x.policies().less(y.iter(), x.iter());
return x.policies().distance(y, x) <= 0;
}
#endif
@ -347,11 +340,8 @@ namespace detail {
template <class Iter>
inline operator_arrow_proxy<typename Iter::value_type>
operator_arrow(const Iter& i, std::input_iterator_tag) {
return operator_arrow_proxy<
#ifndef BOOST_MSVC
typename
#endif
Iter::value_type>(*i);
typedef typename Iter::value_type value_t; // VC++ needs this typedef
return operator_arrow_proxy<value_t>(*i);
}
template <class Iter>
@ -364,7 +354,6 @@ namespace detail {
struct operator_arrow_result_generator
{
typedef operator_arrow_proxy<Value> proxy;
// Borland chokes unless it's an actual enum (!)
enum { is_input_iter
= (boost::is_convertible<Category*,std::input_iterator_tag*>::value
@ -417,7 +406,7 @@ namespace detail {
{
BOOST_STATIC_CONSTANT(bool, is_ptr = boost::is_pointer<Iterator>::value);
typedef iterator_defaults_select<is_ptr>::template traits<Iterator,Value> traits;
typedef typename iterator_defaults_select<is_ptr>::template traits<Iterator,Value> traits;
typedef typename traits::pointer pointer;
typedef typename traits::reference reference;
};
@ -446,25 +435,45 @@ namespace detail {
//===========================================================================
// Specify the defaults for iterator_adaptor's template parameters
struct default_argument { };
// This class template is a workaround for MSVC.
struct dummy_default_gen {
template <class Base, class Traits>
struct select { typedef default_argument type; };
};
// This class template is a workaround for MSVC.
template <class Gen> struct default_generator {
typedef dummy_default_gen type;
};
struct default_value_type {
template <class Base, class Traits>
struct select {
typedef typename boost::detail::iterator_traits<Base>::value_type type;
};
};
template <> struct default_generator<default_value_type>
{ typedef default_value_type type; }; // VC++ workaround
struct default_difference_type {
template <class Base, class Traits>
struct select {
typedef typename boost::detail::iterator_traits<Base>::difference_type type;
};
};
template <> struct default_generator<default_difference_type>
{ typedef default_difference_type type; }; // VC++ workaround
struct default_iterator_category {
template <class Base, class Traits>
struct select {
typedef typename boost::detail::iterator_traits<Base>::iterator_category type;
};
};
template <> struct default_generator<default_iterator_category>
{ typedef default_iterator_category type; }; // VC++ workaround
struct default_pointer {
template <class Base, class Traits>
struct select {
@ -473,6 +482,9 @@ namespace detail {
type;
};
};
template <> struct default_generator<default_pointer>
{ typedef default_pointer type; }; // VC++ workaround
struct default_reference {
template <class Base, class Traits>
struct select {
@ -481,72 +493,241 @@ namespace detail {
type;
};
};
template <> struct default_generator<default_reference>
{ typedef default_reference type; }; // VC++ workaround
} // namespace detail
//===========================================================================
// Support for named template parameters
#if !defined(__BORLANDC__)
// Borland C++ thinks the nested recursive inheritance here is illegal.
struct named_template_param_base { };
template <class V = default_argument,
class R = default_argument,
class P = default_argument,
class C = default_argument,
class D = default_argument>
struct iter_traits_gen : public named_template_param_base {
template <class T>
struct value_type : public iter_traits_gen<T,R,P,C,D> { };
template <class T>
struct reference : public iter_traits_gen<V,T,P,C,D> { };
template <class T>
struct pointer : public iter_traits_gen<V,R,T,C,D> { };
template <class T>
struct iterator_category : public iter_traits_gen<V,R,P,T,D>{};
template <class T>
struct difference_type : public iter_traits_gen<V,R,P,C,T> { };
namespace detail {
struct value_type_tag { };
struct reference_tag { };
struct pointer_tag { };
struct difference_type_tag { };
struct iterator_category_tag { };
typedef boost::iterator<C, V, D, P, R> traits;
// avoid using std::pair because A or B might be a reference type, and g++
// complains about forming references to references inside std::pair
template <class A, class B>
struct cons_type {
typedef A first_type;
typedef B second_type;
};
} // namespace detail
template <class Value> struct value_type_is : public named_template_param_base
{
typedef detail::cons_type<detail::value_type_tag, Value> type;
};
template <class Reference> struct reference_is : public named_template_param_base
{
typedef detail::cons_type<detail::reference_tag, Reference> type;
};
template <class Pointer> struct pointer_is : public named_template_param_base
{
typedef detail::cons_type<detail::pointer_tag, Pointer> type;
};
template <class Difference> struct difference_type_is
: public named_template_param_base
{
typedef detail::cons_type<detail::difference_type_tag, Difference> type;
};
template <class IteratorCategory> struct iterator_category_is
: public named_template_param_base
{
typedef detail::cons_type<detail::iterator_category_tag, IteratorCategory> type;
};
namespace detail {
struct end_of_list { };
// Given an associative list, find the value with the matching key.
// An associative list is a list of key-value pairs. The list is
// built out of cons_type's and is terminated by end_of_list.
#if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) || defined(__BORLANDC__)
template <class AssocList, class Key>
struct find_param;
struct find_param_continue {
template <class AssocList, class Key2> struct select {
typedef typename AssocList::first_type Head;
typedef typename Head::first_type Key1;
typedef typename Head::second_type Value;
typedef typename if_true<(is_same<Key1, Key2>::value)>::template
then<Value,
typename find_param<typename AssocList::second_type, Key2>::type
>::type type;
};
};
struct find_param_end {
template <class AssocList, class Key>
struct select { typedef detail::default_argument type; };
};
template <class AssocList> struct find_param_helper1
{ typedef find_param_continue type; };
template <> struct find_param_helper1<end_of_list>
{ typedef find_param_end type; };
template <class AssocList, class Key>
struct find_param {
typedef typename find_param_helper1<AssocList>::type select1;
typedef typename select1::template select<AssocList, Key>::type type;
};
#else
template <class AssocList, class Key> struct find_param;
template <class Key>
struct find_param<end_of_list, Key> { typedef default_argument type; };
// Found a matching Key, return the associated Value
template <class Key, class Value, class Rest>
struct find_param<detail::cons_type< detail::cons_type<Key, Value>, Rest>, Key> {
typedef Value type;
};
// Non-matching keys, continue the search
template <class Key1, class Value, class Rest, class Key2>
struct find_param<detail::cons_type< detail::cons_type<Key1, Value>, Rest>, Key2> {
typedef typename find_param<Rest, Key2>::type type;
};
#endif
BOOST_NAMED_TEMPLATE_PARAM(value_type);
BOOST_NAMED_TEMPLATE_PARAM(reference);
BOOST_NAMED_TEMPLATE_PARAM(pointer);
BOOST_NAMED_TEMPLATE_PARAM(iterator_category);
BOOST_NAMED_TEMPLATE_PARAM(difference_type);
struct make_named_arg {
template <class Key, class Value>
struct select { typedef typename Value::type type; };
};
struct make_key_value {
template <class Key, class Value>
struct select { typedef detail::cons_type<Key, Value> type; };
};
template <class Value>
struct is_named_parameter
{
enum { value = is_convertible<Value, named_template_param_base>::value };
};
#if defined(__MWERKS__) && __MWERKS__ <= 0x2405 // workaround for broken is_convertible implementation
template <class T> struct is_named_parameter<value_type_is<T> > { enum { value = true }; };
template <class T> struct is_named_parameter<reference_is<T> > { enum { value = true }; };
template <class T> struct is_named_parameter<pointer_is<T> > { enum { value = true }; };
template <class T> struct is_named_parameter<difference_type_is<T> > { enum { value = true }; };
template <class T> struct is_named_parameter<iterator_category_is<T> > { enum { value = true }; };
#endif
template <class Key, class Value>
struct make_arg {
#ifdef __BORLANDC__
// Borland C++ doesn't like the extra indirection of is_named_parameter
typedef typename
if_true<(is_convertible<Value,named_template_param_base>::value)>::
template then<make_named_arg, make_key_value>::type Make;
#else
enum { is_named = is_named_parameter<Value>::value };
typedef typename if_true<(is_named)>::template
then<make_named_arg, make_key_value>::type Make;
#endif
typedef typename Make::template select<Key, Value>::type type;
};
// Mechanism for resolving the default argument for a template parameter.
template <class T> struct is_default { typedef type_traits::no_type type; };
template <> struct is_default<default_argument>
{ typedef type_traits::yes_type type; };
struct choose_default {
template <class Arg, class DefaultGen, class Base, class Traits>
struct select {
typedef typename default_generator<DefaultGen>::type Gen;
typedef typename Gen::template select<Base,Traits>::type type;
};
};
struct choose_arg {
template <class Arg, class DefaultGen, class Base, class Traits>
struct select {
typedef Arg type;
};
};
template <class UseDefault>
struct choose_arg_or_default { typedef choose_arg type; };
template <> struct choose_arg_or_default<type_traits::yes_type> {
typedef choose_default type;
};
template <class Arg, class DefaultGen, class Base, class Traits>
class resolve_default {
typedef typename choose_arg_or_default<typename is_default<Arg>::type>::type
Selector;
public:
typedef typename Selector
::template select<Arg, DefaultGen, Base, Traits>::type type;
};
template <class Base, class Value, class Reference, class Pointer,
class Category, class Distance>
class iterator_adaptor_traits_gen
{
// Form an associative list out of the template parameters
// If the argument is a normal parameter (not named) then make_arg
// creates a key-value pair. If the argument is a named parameter,
// then make_arg extracts the key-value pair defined inside the
// named parameter.
typedef detail::cons_type< typename make_arg<value_type_tag, Value>::type,
detail::cons_type<typename make_arg<reference_tag, Reference>::type,
detail::cons_type<typename make_arg<pointer_tag, Pointer>::type,
detail::cons_type<typename make_arg<iterator_category_tag, Category>::type,
detail::cons_type<typename make_arg<difference_type_tag, Distance>::type,
end_of_list> > > > > ArgList;
// Search the list for particular parameters
typedef typename find_param<ArgList, value_type_tag>::type Val;
typedef typename find_param<ArgList, difference_type_tag>::type Diff;
typedef typename find_param<ArgList, iterator_category_tag>::type Cat;
typedef typename find_param<ArgList, pointer_tag>::type Ptr;
typedef typename find_param<ArgList, reference_tag>::type Ref;
typedef boost::iterator<Category, Value, Distance, Pointer, Reference>
Traits0;
typedef typename get_value_type<Base,
typename boost::remove_const<Value>::type, Traits0
>::type value_type;
typedef typename get_difference_type<Base, Distance, Traits0>::type
difference_type;
typedef typename get_iterator_category<Base, Category, Traits0>::type
iterator_category;
// Compute the defaults if necessary
typedef typename resolve_default<Val, default_value_type, Base, Traits0>::type
value_type;
// if getting default value type from iterator_traits, then it won't be const
typedef typename resolve_default<Diff, default_difference_type, Base,
Traits0>::type difference_type;
typedef typename resolve_default<Cat, default_iterator_category, Base,
Traits0>::type iterator_category;
typedef boost::iterator<iterator_category, value_type, difference_type,
Pointer, Reference> Traits1;
// Compute the defaults for pointer and reference. This is done as a
// separate step because the defaults for pointer and reference depend
// on value_type.
typedef typename resolve_default<Ptr, default_pointer, Base, Traits1>::type
pointer;
typedef typename resolve_default<Ref, default_reference, Base, Traits1>::type
reference;
typedef typename get_pointer<Base, Pointer, Traits1>::type pointer;
typedef typename get_reference<Base, Reference, Traits1>::type reference;
public:
typedef boost::iterator<iterator_category, value_type, difference_type,
pointer, reference> type;
typedef boost::iterator<iterator_category,
typename remove_const<value_type>::type,
difference_type, pointer, reference> type;
};
} // namespace detail
#if !defined(__BORLANDC__)
struct iterator_traits_generator
: public detail::iter_traits_gen<> { };
#endif
// This macro definition is only temporary in this file
# if !defined(BOOST_MSVC)
@ -587,10 +768,10 @@ template <class T> struct undefined;
// supplied, iterator_traits<Base>::difference_type is used.
template <class Base, class Policies,
class Value = detail::default_argument,
class Reference = BOOST_ARG_DEPENDENT_TYPENAME detail::choose_default_argument<Value>::type,
class Pointer = BOOST_ARG_DEPENDENT_TYPENAME detail::choose_default_argument<Reference>::type,
class Category = BOOST_ARG_DEPENDENT_TYPENAME detail::choose_default_argument<Pointer>::type,
class Distance = BOOST_ARG_DEPENDENT_TYPENAME detail::choose_default_argument<Category>::type
class Reference = detail::default_argument,
class Pointer = detail::default_argument,
class Category = detail::default_argument,
class Distance = detail::default_argument
>
struct iterator_adaptor :
#ifdef BOOST_RELOPS_AMBIGUITY_BUG
@ -604,7 +785,8 @@ struct iterator_adaptor :
{
typedef iterator_adaptor<Base,Policies,Value,Reference,Pointer,Category,Distance> self;
public:
typedef typename detail::iterator_adaptor_traits_gen<Base,Value,Reference,Pointer,Category,Distance>::type Traits;
typedef detail::iterator_adaptor_traits_gen<Base,Value,Reference,Pointer,Category,Distance> TraitsGen;
typedef typename TraitsGen::type Traits;
typedef typename Traits::difference_type difference_type;
typedef typename Traits::value_type value_type;
@ -623,6 +805,7 @@ struct iterator_adaptor :
// Iterators should satisfy one of the known categories
BOOST_STATIC_ASSERT(is_input_or_output_iter);
#if !defined(BOOST_MSVC)
// Iterators >= ForwardIterator must produce real references
// as required by the C++ standard requirements in Table 74.
BOOST_STATIC_CONSTANT(bool, forward_iter_with_real_reference =
@ -630,7 +813,6 @@ struct iterator_adaptor :
|| boost::is_same<reference,value_type&>::value
|| boost::is_same<reference,const value_type&>::value));
#if !defined(BOOST_MSVC)
// This check gives incorrect results in iter_traits_gen_test.cpp
BOOST_STATIC_ASSERT(forward_iter_with_real_reference);
#endif
@ -641,15 +823,15 @@ struct iterator_adaptor :
explicit
iterator_adaptor(const Base& it, const Policies& p = Policies())
: m_iter_p(it, p) {
policies().initialize(iter());
policies().initialize(base());
}
template <class Iter2, class Value2, class Pointer2, class Reference2>
iterator_adaptor (
const iterator_adaptor<Iter2,Policies,Value2,Reference2,Pointer2,Category,Distance>& src)
: m_iter_p(src.iter(), src.policies())
: m_iter_p(src.base(), src.policies())
{
policies().initialize(iter());
policies().initialize(base());
}
#if defined(BOOST_MSVC) || defined(__BORLANDC__)
@ -661,7 +843,7 @@ struct iterator_adaptor :
}
#endif
reference operator*() const {
return policies().dereference(type<reference>(), iter());
return policies().dereference(*this);
}
#ifdef BOOST_MSVC
@ -681,12 +863,12 @@ struct iterator_adaptor :
{ return *(*this + n); }
self& operator++() {
#ifdef __MWERKS__
#if !defined(__MWERKS__) || __MWERKS__ >= 0x2405
policies().increment(*this);
#else
// Odd bug, MWERKS couldn't deduce the type for the member template
// Workaround by explicitly specifying the type.
policies().increment<Base>(iter());
#else
policies().increment(iter());
policies().increment<self>(*this);
#endif
return *this;
}
@ -694,10 +876,10 @@ struct iterator_adaptor :
self operator++(int) { self tmp(*this); ++*this; return tmp; }
self& operator--() {
#ifdef __MWERKS__
policies().decrement<Base>(iter());
#if !defined(__MWERKS__) || __MWERKS__ >= 0x2405
policies().decrement(*this);
#else
policies().decrement(iter());
policies().decrement<self>(*this);
#endif
return *this;
}
@ -705,16 +887,16 @@ struct iterator_adaptor :
self operator--(int) { self tmp(*this); --*this; return tmp; }
self& operator+=(difference_type n) {
policies().advance(iter(), n);
policies().advance(*this, n);
return *this;
}
self& operator-=(difference_type n) {
policies().advance(iter(), -n);
policies().advance(*this, -n);
return *this;
}
base_type base() const { return m_iter_p.first(); }
base_type const& base() const { return m_iter_p.first(); }
// Moved from global scope to avoid ambiguity with the operator-() which
// subtracts iterators from one another.
@ -724,11 +906,9 @@ private:
compressed_pair<Base,Policies> m_iter_p;
public: // implementation details (too many compilers have trouble when these are private).
base_type& base() { return m_iter_p.first(); }
Policies& policies() { return m_iter_p.second(); }
const Policies& policies() const { return m_iter_p.second(); }
Base& iter() { return m_iter_p.first(); }
const Base& iter() const { return m_iter_p.first(); }
};
template <class Base, class Policies, class Value, class Reference, class Pointer,
@ -761,7 +941,7 @@ operator-(
{
typedef typename iterator_adaptor<Iterator1,Policies,Value1,Reference1,
Pointer1,Category,Distance>::difference_type difference_type;
return x.policies().distance(type<difference_type>(), y.iter(), x.iter());
return x.policies().distance(y, x);
}
#ifndef BOOST_RELOPS_AMBIGUITY_BUG
@ -773,7 +953,7 @@ operator==(
const iterator_adaptor<Iterator1,Policies,Value1,Reference1,Pointer1,Category,Distance>& x,
const iterator_adaptor<Iterator2,Policies,Value2,Reference2,Pointer2,Category,Distance>& y)
{
return x.policies().equal(x.iter(), y.iter());
return x.policies().equal(x, y);
}
template <class Iterator1, class Iterator2, class Policies, class Value1, class Value2,
@ -784,7 +964,7 @@ operator<(
const iterator_adaptor<Iterator1,Policies,Value1,Reference1,Pointer1,Category,Distance>& x,
const iterator_adaptor<Iterator2,Policies,Value2,Reference2,Pointer2,Category,Distance>& y)
{
return x.policies().less(x.iter(), y.iter());
return x.policies().distance(y, x) < 0;
}
template <class Iterator1, class Iterator2, class Policies, class Value1, class Value2,
@ -795,7 +975,7 @@ operator>(
const iterator_adaptor<Iterator1,Policies,Value1,Reference1,Pointer1,Category,Distance>& x,
const iterator_adaptor<Iterator2,Policies,Value2,Reference2,Pointer2,Category,Distance>& y)
{
return x.policies().less(y.iter(), x.iter());
return x.policies().distance(y, x) > 0;
}
template <class Iterator1, class Iterator2, class Policies, class Value1, class Value2,
@ -806,7 +986,7 @@ operator>=(
const iterator_adaptor<Iterator1,Policies,Value1,Reference1,Pointer1,Category,Distance>& x,
const iterator_adaptor<Iterator2,Policies,Value2,Reference2,Pointer2,Category,Distance>& y)
{
return !x.policies().less(x.iter(), y.iter());
return x.policies().distance(y, x) >= 0;
}
template <class Iterator1, class Iterator2, class Policies, class Value1, class Value2,
@ -817,7 +997,7 @@ operator<=(
const iterator_adaptor<Iterator1,Policies,Value1,Reference1,Pointer1,Category,Distance>& x,
const iterator_adaptor<Iterator2,Policies,Value2,Reference2,Pointer2,Category,Distance>& y)
{
return !x.policies().less(y.iter(), x.iter());
return x.policies().distance(y, x) <= 0;
}
template <class Iterator1, class Iterator2, class Policies, class Value1, class Value2,
@ -828,7 +1008,7 @@ operator!=(
const iterator_adaptor<Iterator1,Policies,Value1,Reference1,Pointer1,Category,Distance>& x,
const iterator_adaptor<Iterator2,Policies,Value2,Reference2,Pointer2,Category,Distance>& y)
{
return !x.policies().equal(x.iter(), y.iter());
return !x.policies().equal(x, y);
}
#endif
@ -844,9 +1024,10 @@ struct transform_iterator_policies : public default_iterator_policies
transform_iterator_policies() { }
transform_iterator_policies(const AdaptableUnaryFunction& f) : m_f(f) { }
template <class Reference, class Iterator>
Reference dereference(type<Reference>, const Iterator& iter) const
{ return m_f(*iter); }
template <class IteratorAdaptor>
typename IteratorAdaptor::reference
dereference(const IteratorAdaptor& iter) const
{ return m_f(*iter.base()); }
AdaptableUnaryFunction m_f;
};
@ -889,9 +1070,9 @@ make_transform_iterator(
struct indirect_iterator_policies : public default_iterator_policies
{
template <class Reference, class Iterator>
Reference dereference(type<Reference>, const Iterator& x) const
{ return **x; }
template <class IteratorAdaptor>
typename IteratorAdaptor::reference dereference(const IteratorAdaptor& x) const
{ return **x.base(); }
};
namespace detail {
@ -984,34 +1165,30 @@ make_indirect_iterator(OuterIterator base)
struct reverse_iterator_policies : public default_iterator_policies
{
template <class Reference, class BidirectionalIterator>
Reference dereference(type<Reference>, const BidirectionalIterator& x) const
{ return *boost::prior(x); }
template <class IteratorAdaptor>
typename IteratorAdaptor::reference dereference(const IteratorAdaptor& x) const
{ return *boost::prior(x.base()); }
template <class BidirectionalIterator>
void increment(BidirectionalIterator& x) const
{ --x; }
{ --x.base(); }
template <class BidirectionalIterator>
void decrement(BidirectionalIterator& x) const
{ ++x; }
{ ++x.base(); }
template <class BidirectionalIterator, class DifferenceType>
void advance(BidirectionalIterator& x, DifferenceType n) const
{ x -= n; }
{ x.base() -= n; }
template <class Difference, class Iterator1, class Iterator2>
Difference distance(type<Difference>, const Iterator1& x,
const Iterator2& y) const
{ return x - y; }
template <class Iterator1, class Iterator2>
typename Iterator1::difference_type distance(
const Iterator1& x, const Iterator2& y) const
{ return x.base() - y.base(); }
template <class Iterator1, class Iterator2>
bool equal(const Iterator1& x, const Iterator2& y) const
{ return x == y; }
template <class Iterator1, class Iterator2>
bool less(const Iterator1& x, const Iterator2& y) const
{ return y < x; }
{ return x.base() == y.base(); }
};
template <class BidirectionalIterator,
@ -1044,9 +1221,9 @@ struct projection_iterator_policies : public default_iterator_policies
projection_iterator_policies() { }
projection_iterator_policies(const AdaptableUnaryFunction& f) : m_f(f) { }
template <class Reference, class Iterator>
Reference dereference (type<Reference>, Iterator const& iter) const {
return m_f(*iter);
template <class IteratorAdaptor>
typename IteratorAdaptor::reference dereference(IteratorAdaptor const& iter) const {
return m_f(*iter.base());
}
AdaptableUnaryFunction m_f;
@ -1113,28 +1290,29 @@ public:
// The Iter template argument is neccessary for compatibility with a MWCW
// bug workaround
template <class Iter>
void increment(Iter& x) {
++x;
satisfy_predicate(x);
template <class IteratorAdaptor>
void increment(IteratorAdaptor& x) {
++x.base();
satisfy_predicate(x.base());
}
template <class Reference, class Iter>
Reference dereference(type<Reference>, const Iter& x) const
{ return *x; }
template <class IteratorAdaptor>
typename IteratorAdaptor::reference dereference(const IteratorAdaptor& x) const
{ return *x.base(); }
template <class Iterator1, class Iterator2>
bool equal(const Iterator1& x, const Iterator2& y) const
{ return x == y; }
template <class IteratorAdaptor1, class IteratorAdaptor2>
bool equal(const IteratorAdaptor1& x, const IteratorAdaptor2& y) const
{ return x.base() == y.base(); }
private:
void satisfy_predicate(Iterator& iter);
Predicate m_predicate;
Iterator m_end;
};
template <class Predicate, class Iterator>
void filter_iterator_policies<Predicate,Iterator>
::satisfy_predicate(Iterator& iter)
void filter_iterator_policies<Predicate,Iterator>::satisfy_predicate(
Iterator& iter)
{
while (m_end != iter && !m_predicate(*iter))
++iter;
@ -1157,7 +1335,7 @@ namespace detail {
template <class Iterator>
struct non_bidirectional_category
{
# if !defined(__MWERKS__) || __MWERKS__ > 0x4000
# if !defined(__MWERKS__) || __MWERKS__ > 0x2405
typedef typename reduce_to_base_class<
std::forward_iterator_tag,
typename iterator_traits<Iterator>::iterator_category

View File

@ -0,0 +1,66 @@
// (C) Copyright Toon Knapen 2001. 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 <boost/iterator_adaptors.hpp>
namespace boost {
template < typename IndexIterator >
struct permutation_iterator_policies : public default_iterator_policies
{
permutation_iterator_policies() {}
permutation_iterator_policies(IndexIterator order_it)
: order_it_( order_it )
{}
template <class IteratorAdaptor>
typename IteratorAdaptor::reference dereference(const IteratorAdaptor& x) const
{ return *(x.base() + *order_it_); }
template <class IteratorAdaptor>
void increment(IteratorAdaptor&)
{ ++order_it_; }
template <class IteratorAdaptor>
void decrement(IteratorAdaptor&)
{ --order_it_; }
template <class IteratorAdaptor, class DifferenceType>
void advance(IteratorAdaptor& x, DifferenceType n)
{ std::advance( order_it_, n ); }
template <class IteratorAdaptor1, class IteratorAdaptor2>
typename IteratorAdaptor1::difference_type
distance(const IteratorAdaptor1& x, const IteratorAdaptor2& y) const
{ return std::distance( x.policies().order_it_, y.policies().order_it_ ); }
template <class IteratorAdaptor1, class IteratorAdaptor2>
bool equal(const IteratorAdaptor1& x, const IteratorAdaptor2& y) const
{ return x.policies().order_it_ == y.policies().order_it_; }
IndexIterator order_it_;
};
template < typename ElementIterator, typename IndexIterator >
struct permutation_iterator_generator
{
typedef boost::iterator_adaptor
< ElementIterator,
permutation_iterator_policies< IndexIterator >
> type;
};
template < class IndexIterator, class ElementIterator >
inline typename permutation_iterator_generator< ElementIterator, IndexIterator >::type
make_permutation_iterator(ElementIterator base, IndexIterator order)
{
typedef typename permutation_iterator_generator< ElementIterator, IndexIterator >::type result_t;
return result_t( base, order );
}
} // namespace boost