mirror of
https://github.com/boostorg/utility.git
synced 2025-05-09 15:04:00 +00:00
commit these changes
[SVN r11563]
This commit is contained in:
parent
ec2ceb9c96
commit
84cdfb032c
@ -52,6 +52,7 @@
|
|||||||
#include <boost/pending/iterator_tests.hpp>
|
#include <boost/pending/iterator_tests.hpp>
|
||||||
#include <boost/pending/integer_range.hpp>
|
#include <boost/pending/integer_range.hpp>
|
||||||
#include <boost/concept_archetype.hpp>
|
#include <boost/concept_archetype.hpp>
|
||||||
|
#include <boost/type_traits/same_traits.hpp>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <deque>
|
#include <deque>
|
||||||
@ -97,6 +98,8 @@ typedef std::deque<int> storage;
|
|||||||
typedef std::deque<int*> pointer_deque;
|
typedef std::deque<int*> pointer_deque;
|
||||||
typedef std::set<storage::iterator> iterator_set;
|
typedef std::set<storage::iterator> iterator_set;
|
||||||
|
|
||||||
|
template <class T> struct foo;
|
||||||
|
|
||||||
int
|
int
|
||||||
main()
|
main()
|
||||||
{
|
{
|
||||||
@ -105,17 +108,54 @@ main()
|
|||||||
const int N = sizeof(array)/sizeof(dummyT);
|
const int N = sizeof(array)/sizeof(dummyT);
|
||||||
|
|
||||||
// sanity check, if this doesn't pass the test is buggy
|
// sanity check, if this doesn't pass the test is buggy
|
||||||
boost::random_access_iterator_test(array,N,array);
|
boost::random_access_iterator_test(array, N, array);
|
||||||
|
|
||||||
|
#if 0
|
||||||
// Check that the policy concept checks and the default policy
|
// Check that the policy concept checks and the default policy
|
||||||
// implementation match up.
|
// implementation match up.
|
||||||
boost::function_requires<
|
boost::function_requires<
|
||||||
boost::RandomAccessIteratorPoliciesConcept<
|
boost::RandomAccessIteratorPoliciesConcept<
|
||||||
boost::default_iterator_policies, int*,
|
boost::default_iterator_policies,
|
||||||
|
boost::iterator_adaptor<int*, boost::default_iterator_policies>,
|
||||||
boost::iterator<std::random_access_iterator_tag, int, std::ptrdiff_t,
|
boost::iterator<std::random_access_iterator_tag, int, std::ptrdiff_t,
|
||||||
int*, int&>
|
int*, int&>
|
||||||
> >();
|
> >();
|
||||||
|
|
||||||
|
// Test the named parameters
|
||||||
|
{
|
||||||
|
// Test computation of defaults
|
||||||
|
typedef boost::iterator_adaptor<int*, boost::default_iterator_policies,
|
||||||
|
boost::value_type_is<int> > Iter1;
|
||||||
|
BOOST_STATIC_ASSERT((boost::is_same<std::iterator_traits<Iter1>::value_type, int>::value));
|
||||||
|
BOOST_STATIC_ASSERT((boost::is_same<std::iterator_traits<Iter1>::reference, int&>::value));
|
||||||
|
BOOST_STATIC_ASSERT((boost::is_same<std::iterator_traits<Iter1>::pointer, int*>::value));
|
||||||
|
BOOST_STATIC_ASSERT((boost::is_same<std::iterator_traits<Iter1>::difference_type, std::ptrdiff_t>::value));
|
||||||
|
BOOST_STATIC_ASSERT((boost::is_same<std::iterator_traits<Iter1>::iterator_category, std::random_access_iterator_tag>::value));
|
||||||
|
}
|
||||||
|
{
|
||||||
|
// Test computation of default when the Value is const
|
||||||
|
typedef boost::iterator_adaptor<int*, boost::default_iterator_policies,
|
||||||
|
boost::value_type_is<const int> > Iter1;
|
||||||
|
BOOST_STATIC_ASSERT((boost::is_same<std::iterator_traits<Iter1>::value_type, int>::value));
|
||||||
|
BOOST_STATIC_ASSERT((boost::is_same<std::iterator_traits<Iter1>::reference, const int&>::value));
|
||||||
|
BOOST_STATIC_ASSERT((boost::is_same<std::iterator_traits<Iter1>::pointer, const int*>::value));
|
||||||
|
}
|
||||||
|
{
|
||||||
|
// Test with no defaults
|
||||||
|
typedef boost::iterator_adaptor<int*, boost::default_iterator_policies,
|
||||||
|
boost::reference_is<long>,
|
||||||
|
boost::pointer_is<float>,
|
||||||
|
boost::value_type_is<char>,
|
||||||
|
boost::iterator_category_is<std::input_iterator_tag>,
|
||||||
|
boost::difference_type_is<int>
|
||||||
|
> Iter1;
|
||||||
|
BOOST_STATIC_ASSERT((boost::is_same<std::iterator_traits<Iter1>::value_type, char>::value));
|
||||||
|
BOOST_STATIC_ASSERT((boost::is_same<std::iterator_traits<Iter1>::reference, long>::value));
|
||||||
|
BOOST_STATIC_ASSERT((boost::is_same<std::iterator_traits<Iter1>::pointer, float>::value));
|
||||||
|
BOOST_STATIC_ASSERT((boost::is_same<std::iterator_traits<Iter1>::difference_type, int>::value));
|
||||||
|
BOOST_STATIC_ASSERT((boost::is_same<std::iterator_traits<Iter1>::iterator_category, std::input_iterator_tag>::value));
|
||||||
|
}
|
||||||
|
|
||||||
// Test the iterator_adaptor
|
// Test the iterator_adaptor
|
||||||
{
|
{
|
||||||
boost::iterator_adaptor<dummyT*, boost::default_iterator_policies, dummyT> i(array);
|
boost::iterator_adaptor<dummyT*, boost::default_iterator_policies, dummyT> i(array);
|
||||||
@ -173,7 +213,7 @@ main()
|
|||||||
|
|
||||||
typedef boost::reverse_iterator_generator<const dummyT*
|
typedef boost::reverse_iterator_generator<const dummyT*
|
||||||
#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
||||||
, const dummyT
|
, dummyT, const dummyT&, const dummyT
|
||||||
#endif
|
#endif
|
||||||
>::type const_reverse_iterator;
|
>::type const_reverse_iterator;
|
||||||
|
|
||||||
@ -306,12 +346,12 @@ main()
|
|||||||
#else
|
#else
|
||||||
typedef boost::iterator_adaptor<boost::forward_iterator_archetype<dummyT>,
|
typedef boost::iterator_adaptor<boost::forward_iterator_archetype<dummyT>,
|
||||||
boost::default_iterator_policies,
|
boost::default_iterator_policies,
|
||||||
boost::iterator_traits_generator
|
boost::reference_is<const dummyT&>,
|
||||||
::value_type<dummyT>
|
boost::pointer_is<const dummyT*> ,
|
||||||
::reference<const dummyT&>
|
boost::iterator_category_is<std::forward_iterator_tag>,
|
||||||
::pointer<const dummyT*>
|
boost::value_type_is<dummyT>,
|
||||||
::iterator_category<std::forward_iterator_tag>
|
boost::difference_type_is<std::ptrdiff_t>
|
||||||
::difference_type<std::ptrdiff_t> > adaptor_type;
|
> adaptor_type;
|
||||||
#endif
|
#endif
|
||||||
adaptor_type i(forward_iter);
|
adaptor_type i(forward_iter);
|
||||||
int zero = 0;
|
int zero = 0;
|
||||||
@ -330,6 +370,7 @@ main()
|
|||||||
if (zero) // don't do this, just make sure it compiles
|
if (zero) // don't do this, just make sure it compiles
|
||||||
assert((*i).m_x == i->foo());
|
assert((*i).m_x == i->foo());
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
std::cout << "test successful " << std::endl;
|
std::cout << "test successful " << std::endl;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -26,6 +26,37 @@
|
|||||||
"../../more/generic_programming.html#adaptors">adaptors</a> which apply
|
"../../more/generic_programming.html#adaptors">adaptors</a> which apply
|
||||||
specific useful behaviors to arbitrary base iterators.
|
specific useful behaviors to arbitrary base iterators.
|
||||||
|
|
||||||
|
<h2>Backward Compatibility Note</h2>
|
||||||
|
|
||||||
|
<p>The library's interface has changed since it was first released, breaking
|
||||||
|
backward compatibility:
|
||||||
|
|
||||||
|
<ol>
|
||||||
|
|
||||||
|
<li><a href="#policies">Policies classes</a> now operate on instances of the
|
||||||
|
whole <tt>iterator_adaptor</tt> object, rather than just operating on the
|
||||||
|
<tt>Base</tt> object. This change not only gives the policies class access
|
||||||
|
to both members of a pair of interacting iterators, but also eliminates the
|
||||||
|
need for the ugly <tt>type<Reference></tt> and
|
||||||
|
<tt>type<Difference></tt> parameters to various policy functions.
|
||||||
|
|
||||||
|
<li>The <a href="#named_template_parameters">Named Template Parameter</a>
|
||||||
|
interface has been made simpler, easier to use, and compatible with more
|
||||||
|
compilers.
|
||||||
|
|
||||||
|
</ol>
|
||||||
|
|
||||||
|
<h2>Other Documentation</h2>
|
||||||
|
|
||||||
|
<p><a href="iterator_adaptors.pdf">``Policy Adaptors and the Boost Iterator
|
||||||
|
Adaptor Library''</a> is a technical paper describing this library and the
|
||||||
|
powerful design pattern on which it is based. It was presented at the <a
|
||||||
|
href="http://www.oonumerics.org/tmpw01">C++ Template Workshop</a> at OOPSLA
|
||||||
|
2001; the slides from the talk are available <a
|
||||||
|
href="iterator_adaptors.ppt">here</a>. Please note that while the slides
|
||||||
|
incorporate the minor interface changes described in the previous section,
|
||||||
|
the paper does not.
|
||||||
|
|
||||||
<h2>Table of Contents</h2>
|
<h2>Table of Contents</h2>
|
||||||
|
|
||||||
<ul>
|
<ul>
|
||||||
@ -183,7 +214,7 @@ struct iterator_adaptor;
|
|||||||
particular, the result type of <tt>operator*()</tt>.<br>
|
particular, the result type of <tt>operator*()</tt>.<br>
|
||||||
<b>Default:</b> If <tt>Value</tt> is supplied, <tt>Value&</tt> is
|
<b>Default:</b> If <tt>Value</tt> is supplied, <tt>Value&</tt> is
|
||||||
used. Otherwise
|
used. Otherwise
|
||||||
<tt>std::iterator_traits<BaseType>::reference</tt> is used.
|
<tt>std::iterator_traits<BaseType>::reference</tt> is used. <a href="#7">[7]</a>
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
<td><tt>Pointer</tt>
|
<td><tt>Pointer</tt>
|
||||||
@ -191,7 +222,7 @@ struct iterator_adaptor;
|
|||||||
<td>The <tt>pointer</tt> type of the resulting iterator, and in
|
<td>The <tt>pointer</tt> type of the resulting iterator, and in
|
||||||
particular, the result type of <tt>operator->()</tt>.<br>
|
particular, the result type of <tt>operator->()</tt>.<br>
|
||||||
<b>Default:</b> If <tt>Value</tt> was supplied, then <tt>Value*</tt>,
|
<b>Default:</b> If <tt>Value</tt> was supplied, then <tt>Value*</tt>,
|
||||||
otherwise <tt>std::iterator_traits<BaseType>::pointer</tt>.
|
otherwise <tt>std::iterator_traits<BaseType>::pointer</tt>. <a href="#7">[7]</a>
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
<td><tt>Category</tt>
|
<td><tt>Category</tt>
|
||||||
@ -385,40 +416,40 @@ typedef iterator_adaptor<foo_iterator, foo_policies,
|
|||||||
<pre>
|
<pre>
|
||||||
struct <a name="default_iterator_policies">default_iterator_policies</a>
|
struct <a name="default_iterator_policies">default_iterator_policies</a>
|
||||||
{
|
{
|
||||||
template <class BaseType>
|
// Some of these members were defined static, but Borland got confused
|
||||||
void initialize(BaseType&)
|
// and thought they were non-const. Also, Sun C++ does not like static
|
||||||
{ }
|
// function templates.
|
||||||
|
|
||||||
template <class Reference, class BaseType>
|
template <class Base>
|
||||||
Reference dereference(type<Reference>, const BaseType& x) const
|
void initialize(Base&)
|
||||||
{ return *x; }
|
{ }
|
||||||
|
|
||||||
template <class BaseType>
|
template <class IteratorAdaptor>
|
||||||
void increment(BaseType& x)
|
typename IteratorAdaptor::reference dereference(const IteratorAdaptor& x) const
|
||||||
{ ++x; }
|
{ return *x.base(); }
|
||||||
|
|
||||||
template <class BaseType1, class BaseType2>
|
template <class IteratorAdaptor>
|
||||||
bool equal(const BaseType1& x, const BaseType2& y) const
|
void increment(IteratorAdaptor& x)
|
||||||
{ return x == y; }
|
{ ++x.base(); }
|
||||||
|
|
||||||
template <class BaseType>
|
template <class IteratorAdaptor>
|
||||||
void decrement(BaseType& x)
|
void decrement(IteratorAdaptor& x)
|
||||||
{ --x; }
|
{ --x.base(); }
|
||||||
|
|
||||||
template <class BaseType, class DifferenceType>
|
template <class IteratorAdaptor, class DifferenceType>
|
||||||
void advance(BaseType& x, DifferenceType n)
|
void advance(IteratorAdaptor& x, DifferenceType n)
|
||||||
{ x += n; }
|
{ x.base() += n; }
|
||||||
|
|
||||||
template <class Difference, class BaseType1, class BaseType2>
|
template <class IteratorAdaptor1, class IteratorAdaptor2>
|
||||||
Difference distance(type<Difference>, const BaseType1& x, const BaseType2& y) const
|
typename IteratorAdaptor1::difference_type
|
||||||
{ return y - x; }
|
distance(const IteratorAdaptor1& x, const IteratorAdaptor2& y) const
|
||||||
|
{ return y.base() - x.base(); }
|
||||||
|
|
||||||
template <class BaseType1, class BaseType2>
|
template <class IteratorAdaptor1, class IteratorAdaptor2>
|
||||||
bool less(const BaseType1& x, const BaseType2& y) const
|
bool equal(const IteratorAdaptor1& x, const IteratorAdaptor2& y) const
|
||||||
{ return x < y; }
|
{ return x.base() == y.base(); }
|
||||||
};
|
};
|
||||||
</pre>
|
</pre></blockquote>
|
||||||
</blockquote>
|
|
||||||
|
|
||||||
<p>Template member functions are used throughout
|
<p>Template member functions are used throughout
|
||||||
<tt>default_iterator_policies</tt> so that it can be employed with a wide
|
<tt>default_iterator_policies</tt> so that it can be employed with a wide
|
||||||
@ -451,7 +482,7 @@ struct <a name="default_iterator_policies">default_iterator_policies</a>
|
|||||||
iterator_adaptor(const
|
iterator_adaptor(const
|
||||||
iterator_adaptor<B,Policies,V,R,P,Category,Distance>&)</tt>
|
iterator_adaptor<B,Policies,V,R,P,Category,Distance>&)</tt>
|
||||||
<br><br>
|
<br><br>
|
||||||
This constructor allows for conversion from non-<tt>const</tt> to
|
This constructor allows for conversion from mutable to
|
||||||
constant adapted iterators. See <a href=
|
constant adapted iterators. See <a href=
|
||||||
"#iterator_interactions">below</a> for more details.<br>
|
"#iterator_interactions">below</a> for more details.<br>
|
||||||
Requires: <tt>B</tt> is convertible to <tt>Base</tt>.
|
Requires: <tt>B</tt> is convertible to <tt>Base</tt>.
|
||||||
@ -483,34 +514,31 @@ struct <a name="default_iterator_policies">default_iterator_policies</a>
|
|||||||
|
|
||||||
<p>To implement a transform iterator we will only change one of the base
|
<p>To implement a transform iterator we will only change one of the base
|
||||||
iterator's behaviors, so the <tt>transform_iterator_policies</tt> class can
|
iterator's behaviors, so the <tt>transform_iterator_policies</tt> class can
|
||||||
inherit the rest from <tt>default_iterator_policies</tt>. We will define
|
inherit the rest from <tt>default_iterator_policies</tt>. We will define the
|
||||||
the <tt>dereference()</tt> member function, which is used to implement
|
<tt>dereference()</tt> member function, which is used to implement
|
||||||
<tt>operator*()</tt> of the adapted iterator. The implementation will
|
<tt>operator*()</tt> of the adapted iterator. The implementation will
|
||||||
dereference the base iterator and apply the function object. The
|
dereference the base iterator and apply the function object. The complete
|
||||||
<tt>type<Reference></tt> parameter is used to convey the appropriate
|
code for <tt>transform_iterator_policies</tt> is:<br>
|
||||||
return type. The complete code for <tt>transform_iterator_policies</tt>
|
|
||||||
is:<br>
|
|
||||||
<br>
|
<br>
|
||||||
|
|
||||||
|
<blockquote><pre>
|
||||||
<blockquote>
|
template <class AdaptableUnaryFunction>
|
||||||
<pre>
|
struct transform_iterator_policies : public default_iterator_policies
|
||||||
template <class AdaptableUnaryFunction>
|
{
|
||||||
struct transform_iterator_policies : public default_iterator_policies
|
|
||||||
{
|
|
||||||
transform_iterator_policies() { }
|
transform_iterator_policies() { }
|
||||||
|
|
||||||
transform_iterator_policies(const AdaptableUnaryFunction& f)
|
transform_iterator_policies(const AdaptableUnaryFunction& f)
|
||||||
: m_f(f) { }
|
: m_f(f) { }
|
||||||
|
|
||||||
template <class Reference, class BaseIterator>
|
template <class IteratorAdaptor>
|
||||||
Reference dereference(type<Reference>, const BaseIterator& i) const
|
typename IteratorAdaptor::reference
|
||||||
{ return m_f(*i); }
|
dereference(const IteratorAdaptor& iter) const
|
||||||
|
{ return m_f(*iter.base()); }
|
||||||
|
|
||||||
AdaptableUnaryFunction m_f;
|
AdaptableUnaryFunction m_f;
|
||||||
};
|
};
|
||||||
</pre>
|
|
||||||
</blockquote>
|
</pre></blockquote>
|
||||||
|
|
||||||
<p>The next step is to use the <tt>iterator_adaptor</tt> template to
|
<p>The next step is to use the <tt>iterator_adaptor</tt> template to
|
||||||
construct the transform iterator type. The nicest way to package the
|
construct the transform iterator type. The nicest way to package the
|
||||||
@ -546,7 +574,7 @@ public:
|
|||||||
|
|
||||||
<p>As a finishing touch, we will create an <a href=
|
<p>As a finishing touch, we will create an <a href=
|
||||||
"../../more/generic_programming.html#object_generator">object generator</a>
|
"../../more/generic_programming.html#object_generator">object generator</a>
|
||||||
for the transform iterator. This is a function that makes it more
|
for the transform iterator. Our object generator makes it more
|
||||||
convenient to create a transform iterator.<br>
|
convenient to create a transform iterator.<br>
|
||||||
<br>
|
<br>
|
||||||
|
|
||||||
@ -785,12 +813,12 @@ bool operator==(const iterator_adaptor<B1,P,V1,R1,P1,C,D>&,
|
|||||||
<tt>reference</tt> types for all <a href=
|
<tt>reference</tt> types for all <a href=
|
||||||
"http://www.sgi.com/tech/stl/ForwardIterator.html">Forward Iterators</a> are
|
"http://www.sgi.com/tech/stl/ForwardIterator.html">Forward Iterators</a> are
|
||||||
<tt>const T*</tt> and <tt>const T&</tt>, respectively. Stripping the
|
<tt>const T*</tt> and <tt>const T&</tt>, respectively. Stripping the
|
||||||
<tt>const</tt>-ness of <tt>Value</tt> allows you to easily
|
<tt>const</tt>-ness of <tt>Value</tt> allows you to easily make a constant
|
||||||
make a <tt>const</tt> iterator adaptor by supplying a <tt>const</tt> type
|
iterator by supplying a <tt>const</tt> type for <tt>Value</tt>, and allowing
|
||||||
for <tt>Value</tt>, and allowing the defaults for the <tt>Pointer</tt> and
|
the defaults for the <tt>Pointer</tt> and <tt>Reference</tt> parameters to
|
||||||
<tt>Reference</tt> parameters to take effect. Although compilers that don't
|
take effect. Although compilers that don't support partial specialization
|
||||||
support partial specialization won't strip <tt>const</tt> for you, having a
|
won't strip <tt>const</tt> for you, having a <tt>const value_type</tt> is
|
||||||
<tt>const value_type</tt> is often harmless in practice.
|
often harmless in practice.
|
||||||
|
|
||||||
<p><a name="2">[2]</a> If your compiler does not support partial
|
<p><a name="2">[2]</a> If your compiler does not support partial
|
||||||
specialization and the base iterator is a builtin pointer type, you
|
specialization and the base iterator is a builtin pointer type, you
|
||||||
@ -856,6 +884,14 @@ bool operator==(const iterator_adaptor<B1,P,V1,R1,P1,C,D>&,
|
|||||||
*x = i;
|
*x = i;
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
|
<p><a name="7">[7]</a>
|
||||||
|
If you are using a compiler that does not have a version of
|
||||||
|
<tt>std::iterator_traits</tt> that works for pointers (i.e., if your
|
||||||
|
compiler does not support partial specialization) then if the
|
||||||
|
<tt>Base</tt> type is a const pointer, then the correct defaults
|
||||||
|
for the <tt>reference</tt> and <tt>pointer</tt> types can not be
|
||||||
|
deduced. You must specify these types explicitly.
|
||||||
|
|
||||||
<hr>
|
<hr>
|
||||||
|
|
||||||
<p>Revised
|
<p>Revised
|
||||||
|
Loading…
x
Reference in New Issue
Block a user