Compare commits

..

13 Commits

Author SHA1 Message Date
nobody
566ba3a832 This commit was manufactured by cvs2svn to create tag
'Version_1_19_0'.

[SVN r8447]
2000-12-10 15:53:47 +00:00
Jeremy Siek
a0e8d1bf36 a C++ standard version of LessThanComparable
[SVN r8435]
2000-12-09 22:39:50 +00:00
Jeremy Siek
912dedaca7 added #include boost/config.hpp at top to remove truncation warning on VC++
[SVN r8434]
2000-12-09 20:28:48 +00:00
Beman Dawes
7dd90c3919 CVS says it needs a commit; who knows why?
[SVN r8405]
2000-12-08 17:35:43 +00:00
Jeremy Siek
7c3a25a377 various changes, almost forgot to check in
[SVN r8379]
2000-12-03 06:20:23 +00:00
Jeremy Siek
c8fbca2d44 added docs for projection iterator
[SVN r8322]
2000-11-24 21:31:43 +00:00
Jeremy Siek
f7ed0aaeed added std:: to unary_function
[SVN r8321]
2000-11-24 20:48:02 +00:00
Jeremy Siek
6e78270140 added projection iterator to the test
[SVN r8320]
2000-11-24 20:45:26 +00:00
Jeremy Siek
ba354377d5 updated docs for indirect iterators
[SVN r8319]
2000-11-24 20:22:23 +00:00
Jeremy Siek
353c030918 simplified version of iterator_adaptor, plus fix to indirect iterator
and addition of projection iterator


[SVN r8317]
2000-11-24 19:40:51 +00:00
John Maddock
331a2b8282 Fixed regex memory leak, and type_traits bad test case
[SVN r8273]
2000-11-21 12:39:09 +00:00
Jeremy Siek
4bd6909ea1 *** empty log message ***
[SVN r8158]
2000-11-07 23:05:04 +00:00
John Maddock
26119613e1 BeOS5 (intel) fixes
[SVN r8133]
2000-11-04 11:16:12 +00:00
10 changed files with 667 additions and 66 deletions

View File

@@ -170,6 +170,28 @@ denotes the address of <tt>u</tt>
<LI><tt>std::pair</tt>
</UL>
<h3>Concept Checking Class</h3>
<pre>
template &lt;class T&gt;
struct CopyConstructibleConcept
{
void constraints() {
T a(b); // require copy constructor
T* ptr = &amp;a; // require address of operator
const_constraints(a);
ignore_unused_variable_warning(ptr);
}
void const_constraints(const T&amp; a) {
T c(a); // require const copy constructor
const T* ptr = &amp;a; // require const address of operator
ignore_unused_variable_warning(c);
ignore_unused_variable_warning(ptr);
}
T b;
};
</pre>
<h3>See also</h3>
<A
href="http://www.sgi.com/Technology/STL/DefaultConstructible.html">DefaultConstructible</A>

212
LessThanComparable.html Normal file
View File

@@ -0,0 +1,212 @@
<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. 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) 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>LessThanComparable</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">
<!--end header-->
<BR Clear>
<H1>LessThanComparable</H1>
<h3>Description</h3>
A type is LessThanComparable if it is ordered: it must
be possible to compare two objects of that type using <tt>operator&lt;</tt>, and
<tt>operator&lt;</tt> must be a strict weak ordering relation.
<h3>Refinement of</h3>
<h3>Associated types</h3>
<h3>Notation</h3>
<Table>
<TR>
<TD VAlign=top>
<tt>X</tt>
</TD>
<TD VAlign=top>
A type that is a model of LessThanComparable
</TD>
</TR>
<TR>
<TD VAlign=top>
<tt>x</tt>, <tt>y</tt>, <tt>z</tt>
</TD>
<TD VAlign=top>
Object of type <tt>X</tt>
</TD>
</tr>
</table>
<h3>Definitions</h3>
Consider the relation <tt>!(x &lt; y) &amp;&amp; !(y &lt; x)</tt>. If this relation is
transitive (that is, if <tt>!(x &lt; y) &amp;&amp; !(y &lt; x) &amp;&amp; !(y &lt; z) &amp;&amp; !(z &lt; y)</tt>
implies <tt>!(x &lt; z) &amp;&amp; !(z &lt; x)</tt>), then it satisfies the mathematical
definition of an equivalence relation. In this case, <tt>operator&lt;</tt>
is a <i>strict weak ordering</i>.
<P>
If <tt>operator&lt;</tt> is a strict weak ordering, and if each equivalence class
has only a single element, then <tt>operator&lt;</tt> is a <i>total ordering</i>.
<h3>Valid expressions</h3>
<Table border>
<TR>
<TH>
Name
</TH>
<TH>
Expression
</TH>
<TH>
Type requirements
</TH>
<TH>
Return type
</TH>
</TR>
<TR>
<TD VAlign=top>
Less
</TD>
<TD VAlign=top>
<tt>x &lt; y</tt>
</TD>
<TD VAlign=top>
&nbsp;
</TD>
<TD VAlign=top>
Convertible to <tt>bool</tt>
</TD>
</TR>
</table>
<h3>Expression semantics</h3>
<Table border>
<TR>
<TH>
Name
</TH>
<TH>
Expression
</TH>
<TH>
Precondition
</TH>
<TH>
Semantics
</TH>
<TH>
Postcondition
</TH>
</TR>
<TR>
<TD VAlign=top>
Less
</TD>
<TD VAlign=top>
<tt>x &lt; y</tt>
</TD>
<TD VAlign=top>
<tt>x</tt> and <tt>y</tt> are in the domain of <tt>&lt;</tt>
</TD>
<TD VAlign=top>
&nbsp;
</TD>
</table>
<h3>Complexity guarantees</h3>
<h3>Invariants</h3>
<Table border>
<TR>
<TD VAlign=top>
Irreflexivity
</TD>
<TD VAlign=top>
<tt>x &lt; x</tt> must be false.
</TD>
</TR>
<TR>
<TD VAlign=top>
Antisymmetry
</TD>
<TD VAlign=top>
<tt>x &lt; y</tt> implies !(y &lt; x) <A href="#2">[2]</A>
</TD>
</TR>
<TR>
<TD VAlign=top>
Transitivity
</TD>
<TD VAlign=top>
<tt>x &lt; y</tt> and <tt>y &lt; z</tt> implies <tt>x &lt; z</tt> <A href="#3">[3]</A>
</TD>
</tr>
</table>
<h3>Models</h3>
<UL>
<LI>
int
</UL>
<h3>Notes</h3>
<P><A name="1">[1]</A>
Only <tt>operator&lt;</tt> is fundamental; the other inequality operators
are essentially syntactic sugar.
<P><A name="2">[2]</A>
Antisymmetry is a theorem, not an axiom: it follows from
irreflexivity and transitivity.
<P><A name="3">[3]</A>
Because of irreflexivity and transitivity, <tt>operator&lt;</tt> always
satisfies the definition of a <i>partial ordering</i>. The definition of
a <i>strict weak ordering</i> is stricter, and the definition of a
<i>total ordering</i> is stricter still.
<h3>See also</h3>
<A href="http://www.sgi.com/Technology/STL/EqualityComparable.html">EqualityComparable</A>, <A href="http://www.sgi.com/Technology/STL/StrictWeakOrdering.html">StrictWeakOrdering</A>
<br>
<HR>
<TABLE>
<TR valign=top>
<TD nowrap>Copyright &copy 2000</TD><TD>
<A HREF=http://www.lsc.nd.edu/~jsiek>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

@@ -134,7 +134,9 @@ template class boost::compressed_pair<empty_UDT, empty_POD_UDT>;
// first references:
template double& compressed_pair<double, int&>::first();
template int& compressed_pair<double, int&>::second();
#if !(defined(__GNUC__) && (__GNUC__ == 2) && (__GNUC_MINOR__ < 95))
template compressed_pair<double, int&>::compressed_pair(int&);
#endif
template compressed_pair<double, int&>::compressed_pair(call_traits<double>::param_type,int&);
//
// and then arrays:
@@ -142,7 +144,9 @@ template compressed_pair<double, int&>::compressed_pair(call_traits<double>::par
template call_traits<int[2]>::reference compressed_pair<double, int[2]>::second();
#endif
template call_traits<double>::reference compressed_pair<double, int[2]>::first();
template compressed_pair<double, int[2]>::compressed_pair(const double&);
#if !(defined(__GNUC__) && (__GNUC__ == 2) && (__GNUC_MINOR__ < 95))
template compressed_pair<double, int[2]>::compressed_pair(call_traits<double>::param_type);
#endif
template compressed_pair<double, int[2]>::compressed_pair();
#endif // __MWERKS__
#endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION

View File

@@ -75,7 +75,9 @@ namespace details
template <typename T>
inline void cp_swap(T& t1, T& t2)
{
#ifndef __GNUC__
using std::swap;
#endif
swap(t1, t2);
}

View File

@@ -7,7 +7,8 @@
#include <functional>
#include <algorithm>
#include <iostream>
#include <boost/iterator_adaptors.hpp>
#include <boost/pending/iterator_adaptors.hpp>
#include <boost/pending/integer_range.hpp>
int
main(int, char*[])
@@ -15,6 +16,7 @@ main(int, char*[])
// This is a simple example of using the transform_iterators class to
// generate iterators that multiply the value returned by dereferencing
// the iterator. In this case we are multiplying by 2.
// Would be cooler to use lambda library in this example.
int x[] = { 1, 2, 3, 4, 5, 6, 7, 8 };

176
iterator_adaptor_test.cpp Normal file
View File

@@ -0,0 +1,176 @@
// Demonstrate and test boost/operators.hpp on std::iterators -------------//
// (C) Copyright Jeremy Siek 1999. 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.
// See http://www.boost.org for most recent version including documentation.
// Revision History
// 13 Jun 00 Added const version of the iterator tests (Jeremy Siek)
// 12 Dec 99 Initial version with iterator operators (Jeremy Siek)
#include <boost/config.hpp>
#include <iostream>
#include <algorithm>
#include <functional>
#include <boost/pending/iterator_adaptors.hpp>
#include <boost/pending/iterator_tests.hpp>
#include <boost/pending/integer_range.hpp>
struct my_iterator_tag : public std::random_access_iterator_tag { };
using boost::dummyT;
struct my_iter_traits {
typedef dummyT value_type;
typedef dummyT* pointer;
typedef dummyT& reference;
typedef my_iterator_tag iterator_category;
typedef std::ptrdiff_t difference_type;
};
struct my_const_iter_traits {
typedef dummyT value_type;
typedef const dummyT* pointer;
typedef const dummyT& reference;
typedef my_iterator_tag iterator_category;
typedef std::ptrdiff_t difference_type;
};
typedef boost::iterator_adaptors
<dummyT*, const dummyT*,
my_iter_traits, my_const_iter_traits> My;
struct mult_functor {
typedef int result_type;
typedef int argument_type;
// Functors used with transform_iterator must be
// DefaultConstructible, as the transform_iterator must be
// DefaultConstructible to satisfy the requirements for
// TrivialIterator.
mult_functor() { }
mult_functor(int aa) : a(aa) { }
int operator()(int b) const { return a * b; }
int a;
};
template <class Pair>
struct select1st_
: public std::unary_function<Pair, typename Pair::first_type>
{
const typename Pair::first_type& operator()(const Pair& x) const {
return x.first;
}
typename Pair::first_type& operator()(Pair& x) const {
return x.first;
}
};
int
main()
{
dummyT array[] = { dummyT(0), dummyT(1), dummyT(2),
dummyT(3), dummyT(4), dummyT(5) };
const int N = sizeof(array)/sizeof(dummyT);
// sanity check, if this doesn't pass the test is buggy
boost::random_access_iterator_test(array,N,array);
// Test the iterator_adaptors
{
My::iterator i = array;
boost::random_access_iterator_test(i, N, array);
My::const_iterator j = array;
boost::random_access_iterator_test(j, N, array);
boost::const_nonconst_iterator_test(i, ++j);
}
// Test transform_iterator
{
int x[N], y[N];
for (int k = 0; k < N; ++k)
x[k] = k;
std::copy(x, x + N, y);
for (int k2 = 0; k2 < N; ++k2)
x[k2] = x[k2] * 2;
boost::transform_iterator<mult_functor, int*,
boost::iterator<std::random_access_iterator_tag,int> >::type
i(y, mult_functor(2));
boost::random_access_iterator_test(i, N, x);
}
// Test indirect_iterators
{
dummyT* ptr[N];
for (int k = 0; k < N; ++k)
ptr[k] = array + k;
typedef boost::indirect_iterators<dummyT**, dummyT*, const dummyT*,
boost::iterator<std::random_access_iterator_tag, dummyT*>,
boost::iterator<std::random_access_iterator_tag, dummyT>,
boost::iterator<std::random_access_iterator_tag, const dummyT>
> Indirect;
Indirect::iterator i = ptr;
boost::random_access_iterator_test(i, N, array);
Indirect::const_iterator j = ptr;
boost::random_access_iterator_test(j, N, array);
boost::const_nonconst_iterator_test(i, ++j);
}
// Test projection_iterators
{
typedef std::pair<dummyT,dummyT> Pair;
Pair pair_array[N];
for (int k = 0; k < N; ++k)
pair_array[k].first = array[k];
typedef boost::projection_iterators<select1st_<Pair>,
Pair*, const Pair*,
boost::iterator<std::random_access_iterator_tag, Pair>,
boost::iterator<std::random_access_iterator_tag, const Pair>
> Projection;
Projection::iterator i = pair_array;
boost::random_access_iterator_test(i, N, array);
Projection::const_iterator j = pair_array;
boost::random_access_iterator_test(j, N, array);
boost::const_nonconst_iterator_test(i, ++j);
}
// Test reverse_iterators
{
dummyT reversed[N];
std::copy(array, array + N, reversed);
std::reverse(reversed, reversed + N);
typedef boost::reverse_iterators<dummyT*, const dummyT*,
boost::iterator<std::random_access_iterator_tag,dummyT>,
boost::iterator<std::random_access_iterator_tag,const dummyT>
> Reverse;
Reverse::iterator i = reversed + N;
boost::random_access_iterator_test(i, N, array);
Reverse::const_iterator j = reversed + N;
boost::random_access_iterator_test(j, N, array);
boost::const_nonconst_iterator_test(i, ++j);
}
// Test integer_range's iterators
{
int int_array[] = { 0, 1, 2, 3, 4, 5 };
boost::integer_range<int> r(0, 5);
boost::random_access_iterator_test(r.begin(), r.size(), int_array);
}
std::cout << "test successful " << std::endl;
return 0;
}

View File

@@ -13,7 +13,9 @@
align="center" width="277" height="86">
<h1>Header
<a href="../../boost/pending/iterator_adaptors.hpp">boost/iterator_adaptors.hpp</a></h1>
<a href="../../boost/pending/iterator_adaptors.hpp">boost/iterator_adaptors.hpp</a>
and
<a href="../../boost/pending/integer_range.hpp">boost/integer_range.hpp</a></h1>
<p>The file <tt>boost/iterator_adaptors.hpp</tt>
includes the main <tt>iterator_adaptors</tt> class and several other classes
@@ -23,8 +25,16 @@ for constructing commonly used iterator adaptors.</p>
<li><a href="#iterator_adaptors"><tt>iterator_adaptors</tt></a>.
<li><a href="#iterator_adaptor"><tt>iterator_adaptor</tt></a>.
<li><a href="#transform_iterator"><tt>transform_iterator</tt></a>
<li><a href="#indirect_iterators"><tt>indirect_iterators</tt></a>
<li><a href="#indirect_iterators"><tt>Indirect Iterator Adaptors</tt></a>
<li><a href="#projection_iterators"><tt>Projection Iterator Adaptors</tt></a>
<li><a href="#reverse_iterators"><tt>reverse_iterators</tt></a>
</ul>
<p>The file <tt>boost/integer_range.hpp</tt> includes a class that
uses iterator adaptors to create an iterator that increments over a
range of integers. The file also includes a &quot;container&quot; type
that creates a container-interface for the range of integers.
<ul>
<li><a href="#integer_range"><tt>integer_range</tt></a>
</ul>
@@ -39,7 +49,11 @@ interactions. He also contributed the <tt>indirect_iterators</tt> and
<a href="http://www.boost.org/people/jeremy_siek.htm">Jeremy Siek</a>
contributed <tt>transform_iterator</tt>, <tt>integer_range</tt>,
and this documentation.
and this documentation.<br>
<a href="http://www.boost.org/people/john_potter.htm">John Potter</a>
contributed <tt>indirect_iterator</tt> and <tt>projection_iterator</tt>
and made some simplifications to <tt>iterator_adaptor</tt>.
<h3><a name="iterator_adaptors">The Iterator Adaptors Class</a></h3>
@@ -60,10 +74,10 @@ follows:
<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0 COLS=2>
<TR><TD WIDTH=30 VALIGN=TOP></TD><TD>
<PRE>
template &lt;class Iterator,
class ConstIterator,
template &lt;class Iterator,
class ConstIterator,
class Traits = std::iterator_traits&lt;Iterator&gt;,
class ConstTraits = std::iterator_traits&lt;ConstIterator&gt;,
class ConstTraits = std::iterator_traits&lt;ConstIterator&gt;,
class Policies = default_iterator_policies&gt;
struct iterator_adaptors
{
@@ -119,7 +133,7 @@ struct default_iterator_policies
{ return *x; }
template &lt;class Iterator&gt;
void increment(Iterator& x) const
static void increment(Iterator& x)
{ ++x; }
template &lt;class Iterator1, class Iterator2&gt;
@@ -128,12 +142,12 @@ struct default_iterator_policies
// required for a BidirectionalIterator
template &lt;class Iterator&gt;
void decrement(Iterator& x) const
static void decrement(Iterator& x)
{ --x; }
// required for a RandomAccessIterator
template &lt;class Iterator, class DifferenceType&gt;
void advance(Iterator& x, DifferenceType n) const
static void advance(Iterator& x, DifferenceType n)
{ x += n; }
template &lt;class Difference, class Iterator1, class Iterator2&gt;
@@ -163,20 +177,18 @@ constructors.
This is the class used inside of the <tt>iterator_adaptors</tt> type
generator. Use this class directly (instead of using
<tt>iterator_adaptors</tt>) when there is no difference between the
const and non-const versions of the iterator type. Often this is
because there is only a const (read-only) version of the iterator, as
is the case for <tt>std::set</tt>'s iterators. Use the same type for
the <tt>Iterator</tt> and <tt>NonconstIterator</tt> template
arguments.
<tt>iterator_adaptors</tt>) when you are interested in creating only
one of the iterator types (either const or non-const) or when there is
no difference between the const and non-const versions of the iterator
type (often this is because there is only a const (read-only) version
of the iterator, as is the case for <tt>std::set</tt>'s iterators).
<p>
<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0 COLS=2>
<TR><TD WIDTH=30 VALIGN=TOP></TD><TD>
<PRE>
template &lt;class Iterator,
template &lt;class Iterator,
class Policies = default_iterator_policies,
class NonconstIterator = Iterator,
class Traits = std::iterator_traits&lt;Iterator&gt; &gt;
struct iterator_adaptor;
</PRE></TD></TABLE>
@@ -219,6 +231,7 @@ href="#2">[2]</a>.
template &lt;class AdaptableUnaryFunction&gt;
struct transform_iterator_policies : public default_iterator_policies
{
transform_iterator_policies() { }
transform_iterator_policies(const AdaptableUnaryFunction& f) : m_f(f) { }
template &lt;class Reference, class Iterator&gt;
@@ -319,67 +332,234 @@ main(int, char*[])
</PRE></TD></TABLE>
<h3><a name="indirect_iterators">The Indirect Iterators Class</a></h3>
<h3><a name="indirect_iterators">The Indirect Iterator Adaptors</a></h3>
It is not all that uncommon to create data structures that consist of
pointers to pointers. For such a structure it might be nice to have an
iterator that applies a double-dereference inside the
<tt>operator*()</tt>. The implementation of this is similar to the
<tt>transform_iterators</tt><a href="#3">[3]</a>. We first create a
policies class which does a double-dereference in the
<tt>dereference()</tt> method. We then create a traits class, this
time also including a template parameter for the traits of the second
level iterators as well as the first. Lastly we wrap this up in the
type generator <tt>indirect_iterators</tt>, using
<tt>iterator_adaptors</tt> to do most of the work.
<tt>transform_iterators</tt><a href="#3">[3]</a>. When talking about a
data structure of pointers to pointers (or more generally, iterators
to iterators), we call the first level iterators the <i>outer</i>
iterators and the second level iterators the <i>inner</i>
iterators. For example, if the outer iterator type is <tt>T**</tt>
then the inner iterator type is <tt>T*</tt>.
To implement the indirect adaptors, we first create a policies class
which does a double-dereference in the <tt>dereference()</tt> method.
<p>
<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0 COLS=2>
<TR><TD WIDTH=30 VALIGN=TOP></TD><TD>
<PRE>
struct indirect_iterator_policies : public default_iterator_policies
{
struct indirect_iterator_policies : public default_iterator_policies
{
template &lt;class Reference, class Iterator&gt;
Reference dereference(type&lt;Reference&gt;, const Iterator& x) const
{ return **x; }
};
{ return **x; }
};
</PRE></TD></TABLE>
template &lt;class IndirectIterator,
class IndirectTraits = std::iterator_traits&lt;IndirectIterator&gt;,
class Traits =
std::iterator_traits&lt;typename IndirectTraits::value_type&gt;
&gt;
struct indirect_traits
{
typedef typename IndirectTraits::difference_type difference_type;
typedef typename Traits::value_type value_type;
typedef typename Traits::pointer pointer;
typedef typename Traits::reference reference;
typedef typename IndirectTraits::iterator_category iterator_category;
};
We then create a traits class, including a template parameter for both
the inner and outer iterators and traits classes. The
<tt>difference_type</tt> and <tt>iterator_category</tt> come from the
outer iterator, while the <tt>value_type</tt>, <tt>pointer</tt>, and
<tt>reference</tt> types come from the inner iterator.
template &lt;class IndirectIterator, class ConstIndirectIterator,
class IndirectTraits =
std::iterator_traits&lt;IndirectIterator&gt;,
class ConstIndirectTraits =
std::iterator_traits&lt;ConstIndirectIterator&gt;,
class Traits =
std::iterator_traits&lt;typename IndirectTraits::value_type&gt;
&gt;
struct indirect_iterators
{
typedef typename IndirectTraits::value_type Iterator;
typedef typename Traits::value_type ValueType;
typedef iterator_adaptors&lt;IndirectIterator, ConstIndirectIterator,
indirect_traits&lt;IndirectIterator, IndirectTraits, Traits&gt;,
indirect_traits&lt;ConstIndirectIterator, ConstIndirectTraits, Traits&gt;,
indirect_iterator_policies
&gt; Adaptors;
<p>
<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0 COLS=2>
<TR><TD WIDTH=30 VALIGN=TOP></TD><TD>
<PRE>
template &lt;class OuterIterator, class InnerIterator,
class OuterTraits = std::iterator_traits&lt;OuterIterator&gt;,
class InnerTraits = std::iterator_traits&lt;InnerIterator&gt;
&gt;
struct indirect_traits
{
typedef typename OuterTraits::difference_type difference_type;
typedef typename InnerTraits::value_type value_type;
typedef typename InnerTraits::pointer pointer;
typedef typename InnerTraits::reference reference;
typedef typename OuterTraits::iterator_category iterator_category;
};
</PRE></TD></TABLE>
Lastly we wrap this up in two type generators:
<tt>indirect_iterator</tt> for creating a single indirect iterator
type, and <tt>indirect_iterators</tt> for creating an const/non-const
pair of indirect iterator types. We use the <tt>iterator_adaptor</tt>
and <tt>iterator_adaptors</tt> classes here to do most of the work.
<p>
<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0 COLS=2>
<TR><TD WIDTH=30 VALIGN=TOP></TD><TD>
<PRE>
template &lt;class OuterIterator, class InnerIterator,
class OuterTraits = std::iterator_traits&lt;OuterIterator&gt;,
class InnerTraits = std::iterator_traits&lt;InnerIterator&gt;
&gt;
struct indirect_iterator
{
typedef iterator_adaptor&lt;OuterIterator,
indirect_iterator_policies,
indirect_traits&lt;OuterIterator, InnerIterator,
OuterTraits, InnerTraits&gt;
&gt; type;
};
template &lt;class OuterIterator, // Mutable or Immutable, does not matter
class InnerIterator, // Mutable
class ConstInnerIterator, // Immutable
class OuterTraits = std::iterator_traits&lt;OuterIterator&gt;,
class InnerTraits = std::iterator_traits&lt;InnerIterator&gt;,
class ConstInnerTraits = std::iterator_traits&lt;ConstInnerIterator&gt;
&gt;
struct indirect_iterators
{
typedef iterator_adaptors&lt;OuterIterator, OuterIterator,
indirect_traits&lt;OuterIterator, InnerIterator,
OuterTraits, InnerTraits&gt;,
indirect_traits&lt;OuterIterator, ConstInnerIterator,
OuterTraits, ConstInnerTraits&gt;,
indirect_iterator_policies
&gt; Adaptors;
typedef typename Adaptors::iterator iterator;
typedef typename Adaptors::const_iterator const_iterator;
};
};
</PRE></TD></TABLE>
<h3><a name="projection_iterators">The Projection Iterator Adaptors</a></h3>
The projection iterator adaptor is very similar to the transform
iterator, except for a subtle difference in the return type: the
tranform iterator returns the result of the unary function by value,
whereas the projection iterator returns the result by reference.
Therefore, these two adaptors cater to different kinds of unary
functions. Transform iterator caters to functions that create new
objects, whereas projection iterator caters to a function that somehow
obtains a reference to an object that already exists. An example of a
unary function that is suitable for use with the projection adaptor is
<tt>select1st_</tt>:
<p>
<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0 COLS=2>
<TR><TD WIDTH=30 VALIGN=TOP></TD><TD>
<PRE>
template &lt;class Pair&gt;
struct select1st_
: public std::unary_function&lt;Pair, typename Pair::first_type&gt;
{
const typename Pair::first_type& operator()(const Pair& x) const {
return x.first;
}
typename Pair::first_type& operator()(Pair& x) const {
return x.first;
}
};
</PRE></TD></TABLE>
The implementation of projection iterator is as follows. First, the
policies class is the same as the transform iterator's policies class.
<p>
<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0 COLS=2>
<TR><TD WIDTH=30 VALIGN=TOP></TD><TD>
<PRE>
template &lt;class AdaptableUnaryFunction&gt;
struct projection_iterator_policies : public default_iterator_policies
{
projection_iterator_policies() { }
projection_iterator_policies(const AdaptableUnaryFunction& f) : m_f(f) { }
template &lt;class Reference, class Iterator&gt;
Reference dereference (type&lt;Reference&gt;, Iterator const& iter) const {
return m_f(*iter);
}
AdaptableUnaryFunction m_f;
};
</PRE></TD></TABLE>
Next we have two traits classes. We use <tt>value_type&</tt> for the
reference type of the mutable projection iterator, and <tt>const
value_type&</tt> for the immutable projection iterator.
<p>
<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0 COLS=2>
<TR><TD WIDTH=30 VALIGN=TOP></TD><TD>
<PRE>
template &lt;class AdaptableUnaryFunction, class Traits&gt;
struct projection_iterator_traits {
typedef typename AdaptableUnaryFunction::result_type value_type;
typedef value_type& reference;
typedef value_type* pointer;
typedef typename Traits::difference_type difference_type;
typedef typename Traits::iterator_category iterator_category;
};
template &lt;class AdaptableUnaryFunction, class Traits&gt;
struct const_projection_iterator_traits {
typedef typename AdaptableUnaryFunction::result_type value_type;
typedef value_type const& reference;
typedef value_type const* pointer;
typedef typename Traits::difference_type difference_type;
typedef typename Traits::iterator_category iterator_category;
};
</PRE></TD></TABLE>
And to finish up, we create three generator classes that
use <tt>iterator_adaptor</tt> to create the projection iterator
types. The class <tt>projection_iterator</tt> creates a mutable
projection iterator type. The class <tt>const_projection_iterator</tt>
creates an immutable projection iterator type, and
<tt>projection_iterators</tt> creates both mutable and immutable
projection iterator types.
<p>
<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0 COLS=2>
<TR><TD WIDTH=30 VALIGN=TOP></TD><TD>
<PRE>
template &lt;class AdaptableUnaryFunction, class Iterator,
class Traits = std::iterator_traits&lt;Iterator&gt;
&gt;
struct projection_iterator {
typedef projection_iterator_traits&lt;AdaptableUnaryFunction, Traits&gt;
Projection_Traits;
typedef iterator_adaptor&lt;Iterator,
projection_iterator_policies&lt;AdaptableUnaryFunction&gt;,
Projection_Traits&gt; type;
};
template &lt;class AdaptableUnaryFunction, class Iterator,
class Traits = std::iterator_traits&lt;Iterator&gt;
&gt;
struct const_projection_iterator {
typedef const_projection_iterator_traits&lt;AdaptableUnaryFunction,
Traits&gt; Projection_Traits;
typedef iterator_adaptor&lt;Iterator,
projection_iterator_policies&lt;AdaptableUnaryFunction&gt;,
Projection_Traits&gt; type;
};
template &lt;class AdaptableUnaryFunction, class Iterator, class ConstIterator,
class Traits = std::iterator_traits&lt;Iterator&gt;,
class ConstTraits = std::iterator_traits&lt;ConstIterator&gt;
&gt;
struct projection_iterators {
typedef projection_iterator_traits&lt;AdaptableUnaryFunction, Traits&gt;
Projection_Traits;
typedef const_projection_iterator_traits&lt;AdaptableUnaryFunction,
ConstTraits&gt; Const_Projection_Traits;
typedef iterator_adaptors&lt;Iterator, ConstIterator,
Projection_Traits, Const_Projection_Traits,
projection_iterator_policies&lt;AdaptableUnaryFunction&gt; &gt; Adaptors;
typedef typename Adaptors::iterator iterator;
typedef typename Adaptors::const_iterator const_iterator;
};
</PRE></TD></TABLE>
<h3><a name="reverse_iterators">The Reverse Iterators Class</a></h3>
<p>
@@ -494,9 +674,9 @@ iterator.
<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0 COLS=2>
<TR><TD WIDTH=30 VALIGN=TOP></TD><TD>
<PRE>
template &lt;class IntegerType&gt;
struct counting_iterator_policies : public default_iterator_policies
{
template &lt;class IntegerType&gt;
IntegerType dereference(type&lt;IntegerType&gt;, const IntegerType& i) const
{ return i; }
};
@@ -617,7 +797,7 @@ uses the three adaptors.
<hr>
<p>Revised <!--webbot bot="Timestamp" s-type="EDITED" s-format="%d %b %Y" startspan -->27 Sep 2000<!--webbot bot="Timestamp" endspan i-checksum="14936" --></p>
<p>Revised <!--webbot bot="Timestamp" s-type="EDITED" s-format="%d %b %Y" startspan -->27 Nov 2000<!--webbot bot="Timestamp" endspan i-checksum="15248" --></p>
<p><EFBFBD> Copyright Jeremy Siek 2000. Permission to copy, use,
modify, sell and distribute this document is granted provided this copyright
notice appears in all copies. This document is provided &quot;as is&quot;

View File

@@ -35,7 +35,7 @@ a function which returns a std::pair&lt;&gt;. The effect of the <TT>tie()</TT>
function is to allow the assignment of the two values of the pair to
two separate variables. The idea for this comes from Jaakko
J&#228;rvi's Binders&nbsp;[<A
HREF="../graph/docs/bibliography.html#jaakko_tuple_assign">1</A>].
HREF="../graph/doc/bibliography.html#jaakko_tuple_assign">1</A>].
<P>

View File

@@ -608,7 +608,7 @@ int main()
value_test(false, (boost::is_convertible<const int *, int*>::value));
value_test(false, (boost::is_convertible<const int&, int&>::value));
value_test(false, (boost::is_convertible<int*, int[2]>::value));
value_test(true, (boost::is_convertible<int*, int[2]>::value));
value_test(false, (boost::is_convertible<const int*, int[3]>::value));
value_test(true, (boost::is_convertible<const int&, int>::value));
value_test(true, (boost::is_convertible<int(&)[4], const int*>::value));
@@ -641,3 +641,4 @@ int main()

View File

@@ -35,6 +35,7 @@ struct ct_checker
#ifdef BOOST_MSVC
#define value_test(v, x) ++test_count;\
{typedef ct_checker<(x)> this_is_a_compile_time_check_;}\
if(!do_compare((int)v,(int)x)){++failures; std::cout << "checking value of " << #x << "...failed" << std::endl;}
#else
#define value_test(v, x) ++test_count;\
@@ -108,3 +109,4 @@ unsigned test_count = 0;
#endif // BOOST_TYPE_TRAITS_TEST_HPP