mirror of
https://github.com/boostorg/utility.git
synced 2025-05-09 02:44:10 +00:00
new documentation
[SVN r7721]
This commit is contained in:
parent
7b02fdb1d9
commit
b70ad177bb
188
CopyConstructible.html
Normal file
188
CopyConstructible.html
Normal file
@ -0,0 +1,188 @@
|
||||
<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.
|
||||
-->
|
||||
<Head>
|
||||
<Title>CopyConstructible</Title>
|
||||
</HEAD>
|
||||
<BODY BGCOLOR="#ffffff" LINK="#0000ee" TEXT="#000000" VLINK="#551a8b"
|
||||
ALINK="#ff0000">
|
||||
<IMG SRC="c++boost.gif"
|
||||
ALT="C++ Boost">
|
||||
<!--end header-->
|
||||
<BR Clear>
|
||||
<H1>CopyConstructible</H1>
|
||||
|
||||
<h3>Description</h3>
|
||||
A type is CopyConstructible if it is possible to copy objects of that
|
||||
type.
|
||||
|
||||
<h3>Notation</h3>
|
||||
<Table>
|
||||
<TR>
|
||||
<TD VAlign=top>
|
||||
<tt>T</tt>
|
||||
</TD>
|
||||
<TD VAlign=top>
|
||||
is type that is a model of CopyConstructible
|
||||
</TD>
|
||||
</TR>
|
||||
|
||||
<TR>
|
||||
<TD VAlign=top>
|
||||
<tt>t</tt>
|
||||
</TD>
|
||||
<TD VAlign=top>
|
||||
is an object of type <tt>T</tt>
|
||||
</TD>
|
||||
</tr>
|
||||
|
||||
<TR>
|
||||
<TD VAlign=top>
|
||||
<tt>u</tt>
|
||||
</TD>
|
||||
<TD VAlign=top>
|
||||
is an object of type <tt>const T</tt>
|
||||
</TD>
|
||||
</tr>
|
||||
|
||||
</table>
|
||||
<h3>Definitions</h3>
|
||||
<h3>Valid expressions</h3>
|
||||
<Table border>
|
||||
<TR>
|
||||
<TH>
|
||||
Name
|
||||
</TH>
|
||||
<TH>
|
||||
Expression
|
||||
</TH>
|
||||
<TH>
|
||||
Return type
|
||||
</TH>
|
||||
<TH>
|
||||
Semantics
|
||||
</TH>
|
||||
</TR>
|
||||
<TR>
|
||||
<TD VAlign=top>
|
||||
Copy constructor
|
||||
</TD>
|
||||
<TD VAlign=top>
|
||||
<tt>T(t)</tt>
|
||||
</TD>
|
||||
<TD VAlign=top>
|
||||
<tt>T</tt>
|
||||
</TD>
|
||||
<TD VAlign=top>
|
||||
<tt>t</tt> is equivalent to <tt>T(t)</tt>
|
||||
</TD>
|
||||
</TR>
|
||||
|
||||
|
||||
<TR>
|
||||
<TD VAlign=top>
|
||||
Copy constructor
|
||||
</TD>
|
||||
<TD VAlign=top>
|
||||
<pre>
|
||||
T(u)
|
||||
</pre>
|
||||
</TD>
|
||||
<TD VAlign=top>
|
||||
<tt>T</tt>
|
||||
</TD>
|
||||
<TD VAlign=top>
|
||||
<tt>u</tt> is equivalent to <tt>T(u)</tt>
|
||||
</TD>
|
||||
</TR>
|
||||
|
||||
|
||||
<TR>
|
||||
<TD VAlign=top>
|
||||
Destructor
|
||||
</TD>
|
||||
<TD VAlign=top>
|
||||
<pre>
|
||||
t.~T()
|
||||
</pre>
|
||||
</TD>
|
||||
<TD VAlign=top>
|
||||
<tt>T</tt>
|
||||
</TD>
|
||||
<TD VAlign=top>
|
||||
|
||||
</TD>
|
||||
</TR>
|
||||
|
||||
<TR>
|
||||
<TD VAlign=top>
|
||||
Address Operator
|
||||
</TD>
|
||||
<TD VAlign=top>
|
||||
<pre>
|
||||
&t
|
||||
</pre>
|
||||
</TD>
|
||||
<TD VAlign=top>
|
||||
<tt>T*</tt>
|
||||
</TD>
|
||||
<TD VAlign=top>
|
||||
denotes the address of <tt>t</tt>
|
||||
</TD>
|
||||
</TR>
|
||||
|
||||
<TR>
|
||||
<TD VAlign=top>
|
||||
Address Operator
|
||||
</TD>
|
||||
<TD VAlign=top>
|
||||
<pre>
|
||||
&u
|
||||
</pre>
|
||||
</TD>
|
||||
<TD VAlign=top>
|
||||
<tt>T*</tt>
|
||||
</TD>
|
||||
<TD VAlign=top>
|
||||
denotes the address of <tt>u</tt>
|
||||
</TD>
|
||||
</TR>
|
||||
|
||||
|
||||
|
||||
</table>
|
||||
|
||||
|
||||
</table>
|
||||
<h3>Models</h3>
|
||||
|
||||
<UL>
|
||||
<LI><tt>int</tt>
|
||||
<LI><tt>std::pair</tt>
|
||||
</UL>
|
||||
|
||||
<h3>See also</h3>
|
||||
<A
|
||||
href="http://www.sgi.com/Technology/STL/DefaultConstructible.html">DefaultConstructible</A>
|
||||
and
|
||||
<A href="http://www.sgi.com/Technology/STL/Assignable.html">Assignable</A>
|
||||
|
||||
<br>
|
||||
<HR>
|
||||
<TABLE>
|
||||
<TR valign=top>
|
||||
<TD nowrap>Copyright © 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>
|
45
iterator_adaptor_examples.cpp
Normal file
45
iterator_adaptor_examples.cpp
Normal file
@ -0,0 +1,45 @@
|
||||
// (C) Copyright Jeremy Siek 2000. 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 <functional>
|
||||
#include <algorithm>
|
||||
#include <iostream>
|
||||
#include <boost/iterator_adaptors.hpp>
|
||||
|
||||
int
|
||||
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.
|
||||
|
||||
int x[] = { 1, 2, 3, 4, 5, 6, 7, 8 };
|
||||
|
||||
typedef std::binder1st< std::multiplies<int> > Function;
|
||||
typedef boost::transform_iterator<Function, int*,
|
||||
boost::iterator<std::random_access_iterator_tag, int>
|
||||
>::type doubling_iterator;
|
||||
|
||||
doubling_iterator i(x, std::bind1st(std::multiplies<int>(), 2)),
|
||||
i_end(x + sizeof(x)/sizeof(int), std::bind1st(std::multiplies<int>(), 2));
|
||||
|
||||
std::cout << "multiplying the array by 2:" << std::endl;
|
||||
while (i != i_end)
|
||||
std::cout << *i++ << " ";
|
||||
std::cout << std::endl;
|
||||
|
||||
// Here is an example of counting from 0 to 5 using the integer_range class.
|
||||
|
||||
boost::integer_range<int> r(0,5);
|
||||
|
||||
std::cout << "counting to from 0 to 4:" << std::endl;
|
||||
std::copy(r.begin(), r.end(), std::ostream_iterator<int>(std::cout, " "));
|
||||
std::cout << std::endl;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
629
iterator_adaptors.htm
Normal file
629
iterator_adaptors.htm
Normal file
@ -0,0 +1,629 @@
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=windows-1252">
|
||||
<meta name="GENERATOR" content="Microsoft FrontPage 4.0">
|
||||
<meta name="ProgId" content="FrontPage.Editor.Document">
|
||||
<title>Header boost/iterator_adaptors.hpp Documentation</title>
|
||||
</head>
|
||||
|
||||
<body bgcolor="#FFFFFF" text="#000000">
|
||||
|
||||
<img src="../../c++boost.gif" alt="c++boost.gif (8819 bytes)"
|
||||
align="center" width="277" height="86">
|
||||
|
||||
<h1>Header
|
||||
<a href="../../boost/pending/iterator_adaptors.hpp">boost/iterator_adaptors.hpp</a></h1>
|
||||
|
||||
<p>The file <tt>boost/iterator_adaptors.hpp</tt>
|
||||
includes the main <tt>iterator_adaptors</tt> class and several other classes
|
||||
for constructing commonly used iterator adaptors.</p>
|
||||
|
||||
<ul>
|
||||
<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="#reverse_iterators"><tt>reverse_iterators</tt></a>
|
||||
<li><a href="#integer_range"><tt>integer_range</tt></a>
|
||||
</ul>
|
||||
|
||||
|
||||
<!-- put in something about Andrei Alexandrescu's contribution? -->
|
||||
|
||||
<p><a href="http://www.boost.org/people/dave_abrahams.htm">Dave
|
||||
Abrahams</a> started the library, coming up with the idea to use
|
||||
policy classes and how to handle the const/non-const iterator
|
||||
interactions. He also contributed the <tt>indirect_iterators</tt> and
|
||||
<tt>reverse_iterators</tt> classes.<br>
|
||||
|
||||
<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.
|
||||
|
||||
<h3><a name="iterator_adaptors">The Iterator Adaptors Class</a></h3>
|
||||
|
||||
Implementing standard conforming iterators is a non-trivial task.
|
||||
There are some fine-points such as iterator/const_iterator
|
||||
interactions and there are the myriad of operators that should be
|
||||
implemented but are easily forgotten such as
|
||||
<tt>operator->()</tt>. The purpose of the
|
||||
<tt>iterator_adaptors</tt> class is to make it easier to implement an
|
||||
iterator class, and even easier to extend and adapt existing iterator
|
||||
types. The <tt>iterator_adaptors</tt> class itself is not an adaptor
|
||||
class but a <i>type generator</i>. It generates a pair of adaptor classes,
|
||||
one class for the mutable iterator and one class for the const
|
||||
iterator. The definition of the <tt>iterator_adaptors</tt> class is as
|
||||
follows:
|
||||
|
||||
<p>
|
||||
<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0 COLS=2>
|
||||
<TR><TD WIDTH=30 VALIGN=TOP></TD><TD>
|
||||
<PRE>
|
||||
template <class Iterator,
|
||||
class ConstIterator,
|
||||
class Traits = std::iterator_traits<Iterator>,
|
||||
class ConstTraits = std::iterator_traits<ConstIterator>,
|
||||
class Policies = default_iterator_policies>
|
||||
struct iterator_adaptors
|
||||
{
|
||||
typedef ... iterator;
|
||||
typedef ... const_iterator;
|
||||
};
|
||||
</PRE></TD></TABLE>
|
||||
|
||||
<p>The <tt>Iterator</tt> and <tt>ConstIterator</tt> template parameters
|
||||
are the iterator types that you want to adapt. The <tt>Traits</tt> and
|
||||
<tt>ConstTraits</tt> must be iterator traits classes. The traits
|
||||
parameters default to the specialization of the
|
||||
<tt>std::iterator_traits</tt> class for the adapted iterators. If you
|
||||
want the traits for your new iterator adaptor (<tt>value_type</tt>,
|
||||
<tt>iterator_category</tt>, etc.) to be the same as the adapted
|
||||
iterator then use the default, otherwise create your own traits
|
||||
classes and pass them in <a href="#1">[1]</a>.
|
||||
|
||||
|
||||
<p>The <tt>Policies</tt> class that you pass in will become the heart of
|
||||
the iterator adaptor. The policy class determines how your new adaptor
|
||||
class will behave. The <tt>Policies</tt> class must implement 3, 4, or
|
||||
7 of the core iterator operations depending on whether you wish the
|
||||
new iterator adaptor class to be a
|
||||
<a href="http://www.sgi.com/Technology/STL/ForwardIterator.html">
|
||||
ForwardIterator</a>,
|
||||
<a href="http://www.sgi.com/Technology/STL/BidirectionalIterator.html">
|
||||
BidirectionalIterator</a>, or <a
|
||||
href="http://www.sgi.com/Technology/STL/RandomAccessIterator.html">
|
||||
RandomAccessIterator</a>. Make sure that the
|
||||
<tt>iterator_category</tt> type of the traits class you pass in
|
||||
matches the category of iterator that you want to create. The default
|
||||
policy class, <tt>default_iterator_policies</tt>, implements all 7 of
|
||||
the core operations in the usual way. If you wish to create an
|
||||
iterator adaptor that only changes a few of the iterator's behaviors,
|
||||
then you can have your new policy class inherit from
|
||||
<tt>default_iterator_policies</tt> to avoid retyping the usual
|
||||
behaviours. You should also look at <tt>default_iterator_policies</tt>
|
||||
as the "boiler-plate" for your own policy classes. The
|
||||
following is definition of the <tt>default_iterator_policies</tt>
|
||||
class:
|
||||
|
||||
|
||||
<p>
|
||||
<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0 COLS=2>
|
||||
<TR><TD WIDTH=30 VALIGN=TOP></TD><TD>
|
||||
<PRE>
|
||||
struct default_iterator_policies
|
||||
{
|
||||
// required for a ForwardIterator
|
||||
template <class Reference, class Iterator>
|
||||
Reference dereference(type<Reference>, const Iterator& x) const
|
||||
{ return *x; }
|
||||
|
||||
template <class Iterator>
|
||||
void increment(Iterator& x) const
|
||||
{ ++x; }
|
||||
|
||||
template <class Iterator1, class Iterator2>
|
||||
bool equal(Iterator1& x, Iterator2& y) const
|
||||
{ return x == y; }
|
||||
|
||||
// required for a BidirectionalIterator
|
||||
template <class Iterator>
|
||||
void decrement(Iterator& x) const
|
||||
{ --x; }
|
||||
|
||||
// required for a RandomAccessIterator
|
||||
template <class Iterator, class DifferenceType>
|
||||
void advance(Iterator& x, DifferenceType n) const
|
||||
{ x += n; }
|
||||
|
||||
template <class Difference, class Iterator1, class Iterator2>
|
||||
Difference distance(type<Difference>, Iterator1& x, Iterator2& y) const
|
||||
{ return y - x; }
|
||||
|
||||
template <class Iterator1, class Iterator2>
|
||||
bool less(Iterator1& x, Iterator2& y) const
|
||||
{ return x < y; }
|
||||
};
|
||||
</PRE></TD></TABLE>
|
||||
|
||||
<p>
|
||||
The generated iterator adaptor types will have the following
|
||||
constructors.
|
||||
|
||||
<p>
|
||||
<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0 COLS=2>
|
||||
<TR><TD WIDTH=30 VALIGN=TOP></TD><TD>
|
||||
<PRE>
|
||||
<i>iterator</i>(const Iterator& i, const Policies& p = Policies())
|
||||
|
||||
<i>const_iterator</i>(const ConstIterator& i, const Policies& p = Policies())
|
||||
</PRE></TD></TABLE>
|
||||
|
||||
<h3><a name="iterator_adaptor">The Iterator Adaptor Class</a></h3>
|
||||
|
||||
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.
|
||||
|
||||
<p>
|
||||
<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0 COLS=2>
|
||||
<TR><TD WIDTH=30 VALIGN=TOP></TD><TD>
|
||||
<PRE>
|
||||
template <class Iterator,
|
||||
class Policies = default_iterator_policies,
|
||||
class NonconstIterator = Iterator,
|
||||
class Traits = std::iterator_traits<Iterator> >
|
||||
struct iterator_adaptor;
|
||||
</PRE></TD></TABLE>
|
||||
|
||||
|
||||
<p>
|
||||
Next we will look at some iterator adaptors that are examples of how
|
||||
to use the iterator adaptors class, and that are useful iterator
|
||||
adaptors in their own right.
|
||||
|
||||
<h3><a name="transform_iterator">The Transform Iterator Class</a></h3>
|
||||
|
||||
It is often useful to automatically apply some function to the value
|
||||
returned by dereferencing (<tt>operator*()</tt>) an iterator. The
|
||||
<tt>transform_iterators</tt> class makes it easy to create an iterator
|
||||
adaptor that does just that.
|
||||
|
||||
First let us consider what the <tt>Policies</tt> class for the transform
|
||||
iterator should look like. We are only changing one of the iterator
|
||||
behaviours, so we will inherit from
|
||||
<tt>default_iterator_policies</tt>. In addition, we will need a
|
||||
function object to apply, so we will have a template parameter and a
|
||||
data member for the function object. The function will take one
|
||||
argument (the dereferenced value) and we will need to know the
|
||||
<tt>result_type</tt> of the function, so <a
|
||||
href="http://www.sgi.com/Technology/STL/AdaptableUnaryFunction.html">
|
||||
AdaptableUnaryFunction</a> is the corrent concept to choose for the
|
||||
function object type. Now for the heart of our iterator adaptor, we
|
||||
implement the <tt>dereference</tt> method, applying the function
|
||||
object to <tt>*i</tt>. The <tt>type<Reference></tt> class is
|
||||
there to tell you what the reference type of the iterator is, which is
|
||||
handy when writing generic iterator adaptors such as this one <a
|
||||
href="#2">[2]</a>.
|
||||
|
||||
|
||||
<p>
|
||||
<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0 COLS=2>
|
||||
<TR><TD WIDTH=30 VALIGN=TOP></TD><TD>
|
||||
<PRE>
|
||||
template <class AdaptableUnaryFunction>
|
||||
struct transform_iterator_policies : public default_iterator_policies
|
||||
{
|
||||
transform_iterator_policies(const AdaptableUnaryFunction& f) : m_f(f) { }
|
||||
|
||||
template <class Reference, class Iterator>
|
||||
Reference dereference(type<Reference>, const Iterator& i) const
|
||||
{ return m_f(*i); }
|
||||
|
||||
AdaptableUnaryFunction m_f;
|
||||
};
|
||||
</PRE></TD></TABLE>
|
||||
|
||||
Next we need to create the traits class for our new iterator. In some
|
||||
situations you may need to create a separate traits class for the
|
||||
const and non-const iterator types, but here a single traits class
|
||||
will do. The <tt>value_type</tt> and <tt>reference</tt> type of our
|
||||
transform iterator will be the <tt>result_type</tt> of the function
|
||||
object. The <tt>difference_type</tt> and <tt>iterator_category</tt>
|
||||
will be the same as the adapted iterator.
|
||||
|
||||
<p>
|
||||
<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0 COLS=2>
|
||||
<TR><TD WIDTH=30 VALIGN=TOP></TD><TD>
|
||||
<PRE>
|
||||
template <class AdaptableUnaryFunction, class IteratorTraits>
|
||||
struct transform_iterator_traits {
|
||||
typedef typename AdaptableUnaryFunction::result_type value_type;
|
||||
typedef value_type reference;
|
||||
typedef value_type* pointer;
|
||||
typedef typename IteratorTraits::difference_type difference_type;
|
||||
typedef typename IteratorTraits::iterator_category iterator_category;
|
||||
};
|
||||
</PRE></TD></TABLE>
|
||||
|
||||
The final step is to use the <tt>iterator_adaptor</tt> class to
|
||||
construct our transform iterator. We will use the single iterator
|
||||
adaptor version because we will not need to create both a mutable and
|
||||
const version of the transform iterator. The transform iterator is
|
||||
inherently a read-only iterator. The nicest way to package up our new
|
||||
transform iterator is to create a type generator similar to
|
||||
<tt>iterator_adaptor</tt>. The first template parameter will be the
|
||||
type of the function object. The second parameter will be the adapted
|
||||
iterator type. The third parameter is the trait class for
|
||||
the adapted iterator. Inside the <tt>transform_iterators</tt> class
|
||||
we use the <tt>transform_iterator_traits</tt> class defined above to
|
||||
create the traits class for the new transform iterator. We then use
|
||||
the <tt>iterator_adaptor</tt> class to extract the generated
|
||||
iterator adaptor type.
|
||||
|
||||
<p>
|
||||
<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0 COLS=2>
|
||||
<TR><TD WIDTH=30 VALIGN=TOP></TD><TD>
|
||||
<PRE>
|
||||
template <class AdaptableUnaryFunction,
|
||||
class Iterator,
|
||||
class Traits = std::iterator_traits<Iterator>
|
||||
>
|
||||
struct transform_iterator
|
||||
{
|
||||
typedef transform_iterator_traits<AdaptableUnaryFunction,Traits>
|
||||
TransTraits;
|
||||
typedef iterator_adaptor<Iterator, TransTraits,
|
||||
transform_iterator_policies<AdaptableUnaryFunction> >::type type;
|
||||
};
|
||||
</PRE></TD></TABLE>
|
||||
|
||||
<p>
|
||||
The following is a simple example of how to use the
|
||||
<tt>transform_iterators</tt> class to iterate through a range of
|
||||
numbers, multiplying each of them by 2 when they are dereferenced.
|
||||
|
||||
<p>
|
||||
<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0 COLS=2>
|
||||
<TR><TD WIDTH=30 VALIGN=TOP></TD><TD>
|
||||
<PRE>
|
||||
#include <functional>
|
||||
#include <iostream>
|
||||
#include <boost/iterator_adaptors.hpp>
|
||||
|
||||
int
|
||||
main(int, char*[])
|
||||
{
|
||||
int x[] = { 1, 2, 3, 4, 5, 6, 7, 8 };
|
||||
|
||||
typedef std::binder1st< std::multiplies<int> > Function;
|
||||
typedef boost::transform_iterator<Function, int*,
|
||||
boost::iterator<std::random_access_iterator_tag, int>
|
||||
>::type doubling_iterator;
|
||||
|
||||
doubling_iterator i(x, std::bind1st(std::multiplies<int>(), 2)),
|
||||
i_end(x + sizeof(x)/sizeof(int), std::bind1st(std::multiplies<int>(), 2));
|
||||
|
||||
std::cout << "multiplying the array by 2:" << std::endl;
|
||||
while (i != i_end)
|
||||
std::cout << *i++ << " ";
|
||||
std::cout << std::endl;
|
||||
|
||||
return 0;
|
||||
}
|
||||
</PRE></TD></TABLE>
|
||||
|
||||
|
||||
<h3><a name="indirect_iterators">The Indirect Iterators Class</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.
|
||||
|
||||
<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
|
||||
{
|
||||
template <class Reference, class Iterator>
|
||||
Reference dereference(type<Reference>, const Iterator& x) const
|
||||
{ return **x; }
|
||||
};
|
||||
|
||||
template <class IndirectIterator,
|
||||
class IndirectTraits = std::iterator_traits<IndirectIterator>,
|
||||
class Traits =
|
||||
std::iterator_traits<typename IndirectTraits::value_type>
|
||||
>
|
||||
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;
|
||||
};
|
||||
|
||||
template <class IndirectIterator, class ConstIndirectIterator,
|
||||
class IndirectTraits =
|
||||
std::iterator_traits<IndirectIterator>,
|
||||
class ConstIndirectTraits =
|
||||
std::iterator_traits<ConstIndirectIterator>,
|
||||
class Traits =
|
||||
std::iterator_traits<typename IndirectTraits::value_type>
|
||||
>
|
||||
struct indirect_iterators
|
||||
{
|
||||
typedef typename IndirectTraits::value_type Iterator;
|
||||
typedef typename Traits::value_type ValueType;
|
||||
typedef iterator_adaptors<IndirectIterator, ConstIndirectIterator,
|
||||
indirect_traits<IndirectIterator, IndirectTraits, Traits>,
|
||||
indirect_traits<ConstIndirectIterator, ConstIndirectTraits, Traits>,
|
||||
indirect_iterator_policies
|
||||
> 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>
|
||||
Yes, there is already a <tt>reverse_iterator</tt> adaptor class
|
||||
defined in the C++ Standard, but using the <tt>iterator_adaptors</tt>
|
||||
class we can re-implement this classic adaptor in a more succinct and
|
||||
elegant fashion. Also, this makes for a good example of using
|
||||
<tt>iterator_adaptors</tt> that is in familiar territory.
|
||||
|
||||
<p>
|
||||
The first step is to create the <tt>Policies</tt> class. As in the
|
||||
<tt>std::reverse_iterator</tt> class, we need to flip all the
|
||||
operations of the iterator. Increment will become decrement, advancing
|
||||
by <tt>n</tt> will become retreating by <tt>n</tt>, etc.
|
||||
|
||||
<p>
|
||||
<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0 COLS=2>
|
||||
<TR><TD WIDTH=30 VALIGN=TOP></TD><TD>
|
||||
<PRE>
|
||||
struct reverse_iterator_policies
|
||||
{
|
||||
template <class Reference, class Iterator>
|
||||
Reference dereference(type<Reference>, const Iterator& x) const
|
||||
{ return *boost::prior(x); }
|
||||
// this is equivalent to { Iterator tmp = x; return *--tmp; }
|
||||
|
||||
template <class Iterator>
|
||||
void increment(Iterator& x) const
|
||||
{ --x; }
|
||||
|
||||
template <class Iterator>
|
||||
void decrement(Iterator& x) const
|
||||
{ ++x; }
|
||||
|
||||
template <class Iterator, class DifferenceType>
|
||||
void advance(Iterator& x, DifferenceType n) const
|
||||
{ x -= n; }
|
||||
|
||||
template <class Difference, class Iterator1, class Iterator2>
|
||||
Difference distance(type<Difference>, Iterator1& x, Iterator2& y) const
|
||||
{ return x - y; }
|
||||
|
||||
template <class Iterator1, class Iterator2>
|
||||
bool equal(Iterator1& x, Iterator2& y) const
|
||||
{ return x == y; }
|
||||
|
||||
template <class Iterator1, class Iterator2>
|
||||
bool less(Iterator1& x, Iterator2& y) const
|
||||
{ return y < x; }
|
||||
};
|
||||
</PRE></TD></TABLE>
|
||||
|
||||
Since the traits of the reverse iterator adaptor will be the same as
|
||||
the adapted iterator's traits, we do not need to create new traits
|
||||
classes as was the case for <tt>transform_iterator</tt>. We can skip to
|
||||
the final stage of creating a type generator class for our reverse
|
||||
iterators using the <tt>iterator_adaptor</tt> class.
|
||||
|
||||
<p>
|
||||
<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0 COLS=2>
|
||||
<TR><TD WIDTH=30 VALIGN=TOP></TD><TD>
|
||||
<PRE>
|
||||
template <class Iterator, class ConstIterator,
|
||||
class Traits = std::iterator_traits<Iterator>,
|
||||
class ConstTraits = std::iterator_traits<ConstIterator>
|
||||
>
|
||||
struct reverse_iterators
|
||||
{
|
||||
typedef iterator_adaptors<Iterator,ConstIterator,Traits,ConstTraits,
|
||||
reverse_iterator_policies> Adaptor;
|
||||
typedef typename Adaptor::iterator iterator;
|
||||
typedef typename Adaptor::const_iterator const_iterator;
|
||||
};
|
||||
</PRE></TD></TABLE>
|
||||
|
||||
A typical use of the <tt>reverse_iterators</tt> class is in
|
||||
user-defined container types. You can use the
|
||||
<tt>reverse_iterators</tt> class to generate the reverse iterators for
|
||||
your container.
|
||||
|
||||
<p>
|
||||
<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0 COLS=2>
|
||||
<TR><TD WIDTH=30 VALIGN=TOP></TD><TD>
|
||||
<PRE>
|
||||
class my_container {
|
||||
...
|
||||
typedef ... iterator;
|
||||
typedef ... const_iterator;
|
||||
|
||||
typedef reverse_iterators<iterator, const_iterator> RevIters;
|
||||
typedef typename RevIters::iterator reverse_iterator;
|
||||
typedef typename RevIters::const_iterator const_reverse_iterator;
|
||||
...
|
||||
};
|
||||
</PRE></TD></TABLE>
|
||||
|
||||
|
||||
<h3><a name="integer_range">The Integer Range Class</a></h3>
|
||||
|
||||
The <tt>iterator_adaptors</tt> class can not only be used for adapting
|
||||
iterators, but it can also be used to take a non-iterator type and use
|
||||
it to build an iterator. An especially simple example of this is
|
||||
turning an integer type into an iterator, a counting iterator. The
|
||||
builtin integer types of C++ are almost iterators. They have
|
||||
<tt>operator++()</tt>, <tt>operator--()</tt>, etc. The one operator
|
||||
they are lacking is the <tt>operator*()</tt>, which we will want to
|
||||
simply return the current value of the integer. The following few
|
||||
lines of code implement the policy and traits class for the counting
|
||||
iterator.
|
||||
|
||||
<p>
|
||||
<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0 COLS=2>
|
||||
<TR><TD WIDTH=30 VALIGN=TOP></TD><TD>
|
||||
<PRE>
|
||||
struct counting_iterator_policies : public default_iterator_policies
|
||||
{
|
||||
template <class IntegerType>
|
||||
IntegerType dereference(type<IntegerType>, const IntegerType& i) const
|
||||
{ return i; }
|
||||
};
|
||||
template <class IntegerType>
|
||||
struct counting_iterator_traits {
|
||||
typedef IntegerType value_type;
|
||||
typedef IntegerType reference;
|
||||
typedef value_type* pointer;
|
||||
typedef std::ptrdiff_t difference_type;
|
||||
typedef std::random_access_iterator_tag iterator_category;
|
||||
};
|
||||
</PRE></TD></TABLE>
|
||||
|
||||
Typically we will want to count the integers in some range, so a nice
|
||||
interface would be to have a fake container that represents the range
|
||||
of integers. The following is the definition of such a class called
|
||||
<tt>integer_range</tt>.
|
||||
|
||||
<p>
|
||||
<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0 COLS=2>
|
||||
<TR><TD WIDTH=30 VALIGN=TOP></TD><TD>
|
||||
<PRE>
|
||||
template <class IntegerType>
|
||||
struct integer_range {
|
||||
typedef typename iterator_adaptor<IntegerType,
|
||||
counting_iterator_traits<IntegerType>,
|
||||
counting_iterator_policies >::type iterator;
|
||||
typedef iterator const_iterator;
|
||||
typedef IntegerType value_type;
|
||||
typedef std::ptrdiff_t difference_type;
|
||||
typedef IntegerType reference;
|
||||
typedef IntegerType* pointer;
|
||||
typedef IntegerType size_type;
|
||||
|
||||
integer_range(IntegerType start, IntegerType finish)
|
||||
: m_start(start), m_finish(finish) { }
|
||||
|
||||
iterator begin() const { return iterator(m_start); }
|
||||
iterator end() const { return iterator(m_finish); }
|
||||
size_type size() const { return m_finish - m_start; }
|
||||
bool empty() const { return m_finish == m_start; }
|
||||
void swap(integer_range& x) {
|
||||
std::swap(m_start, x.m_start);
|
||||
std::swap(m_finish, x.m_finish);
|
||||
}
|
||||
protected:
|
||||
IntegerType m_start, m_finish;
|
||||
};
|
||||
</PRE></TD></TABLE>
|
||||
|
||||
<p>
|
||||
The following is an example of how to use the
|
||||
<tt>integer_range</tt> class to count from 0 to 4.
|
||||
|
||||
<p>
|
||||
<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0 COLS=2>
|
||||
<TR><TD WIDTH=30 VALIGN=TOP></TD><TD>
|
||||
<PRE>
|
||||
boost::integer_range<int> r(0,5);
|
||||
|
||||
cout << "counting to from 0 to 4:" << endl;
|
||||
std::copy(r.begin(), r.end(), ostream_iterator<int>(cout, " "));
|
||||
cout << endl;
|
||||
</PRE></TD></TABLE>
|
||||
|
||||
<h3>Challenge</h3>
|
||||
|
||||
<p>
|
||||
There is an unlimited number of ways the the
|
||||
<tt>iterator_adaptors</tt> class can be used to create iterators. One
|
||||
interesting exercise would be to re-implement the iterators of
|
||||
<tt>std::list</tt> and <tt>std::slist</tt> using
|
||||
<tt>iterator_adaptors</tt>, where the adapted <tt>Iterator</tt> types
|
||||
would be node pointers.
|
||||
|
||||
|
||||
<h3>Notes</h3>
|
||||
|
||||
<p>
|
||||
<a name="1">[1]</a>
|
||||
If your compiler does not support partial specialization and hence
|
||||
does not have a working <tt>std::iterator_traits</tt> class, you will
|
||||
not be able to use the defaults and will need to supply your own
|
||||
<tt>Traits</tt> and <tt>ConstTraits</tt> classes.
|
||||
|
||||
<p>
|
||||
<a name="2">[2]</a>
|
||||
The reference type could also be obtained from
|
||||
<tt>std::iterator_traits</tt>, but that is not portable on compilers
|
||||
that do not support partial specialization.
|
||||
|
||||
<p>
|
||||
<a name="3">[3]</a>
|
||||
It would have been more elegant to implement <tt>indirect_iterators</tt>
|
||||
using <tt>transform_iterators</tt>, but for subtle reasons that would require
|
||||
the use of <tt>boost::remove_cv</tt> which is not portable.
|
||||
|
||||
<h3>Implementation Notes</h3>
|
||||
|
||||
The code is somewhat complicated because there are three iterator
|
||||
adaptor class: <tt>forward_iterator_adaptor</tt>,
|
||||
<tt>bidirectional_iterator_adaptor</tt>, and
|
||||
<tt>random_access_iterator_adaptor</tt>. The alternative would be to
|
||||
just have one iterator adaptor equivalent to the
|
||||
<tt>random_access_iterator_adaptor</tt>. The reason for going with
|
||||
the three adaptors is that according to 14.5.3p5 in the C++ Standard,
|
||||
friend functions defined inside a template class body are instantiated
|
||||
when the template class is instantiated. This means that if we only
|
||||
used the one iterator adaptor, then if the adapted iterator did not
|
||||
meet all of the requirements for a
|
||||
<a href="http://www.sgi.com/Technology/STL/RandomAccessIterator.html">
|
||||
RandomAccessIterator</a> then a compiler error should occur. Many
|
||||
current compilers in fact do not instantiate the friend functions
|
||||
unless used, so we could get away with the one iterator adaptor in
|
||||
most cases. However, out of respect for the standard this implementation
|
||||
uses the three adaptors.
|
||||
|
||||
|
||||
|
||||
<hr>
|
||||
<p>Revised <!--webbot bot="Timestamp" s-type="EDITED" s-format="%d %b %Y" startspan -->17 Jun 2000<!--webbot bot="Timestamp" endspan i-checksum="15055" --></p>
|
||||
<p>© 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 "as is"
|
||||
without express or implied warranty, and with no claim as to its suitability for
|
||||
any purpose.</p>
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
138
tie.html
Normal file
138
tie.html
Normal file
@ -0,0 +1,138 @@
|
||||
<HTML>
|
||||
<!--
|
||||
-- Copyright (c) Jeremy Siek, Lie-Quan Lee, and Andrew Lumsdaine 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. We 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 Tie</Title>
|
||||
<BODY BGCOLOR="#ffffff" LINK="#0000ee" TEXT="#000000" VLINK="#551a8b"
|
||||
ALINK="#ff0000">
|
||||
<IMG SRC="c++boost.gif"
|
||||
ALT="C++ Boost">
|
||||
|
||||
<BR Clear>
|
||||
|
||||
<H1><A NAME="sec:tie"></A>
|
||||
<TT>tie</TT>
|
||||
</H1>
|
||||
|
||||
<P>
|
||||
<PRE>
|
||||
template <class A, class B>
|
||||
tied<A,B> tie(A& a, B& b);
|
||||
</PRE>
|
||||
|
||||
<P>
|
||||
This is a utility function that makes it more convenient to work with
|
||||
a function which returns a pair. 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ärvi's Binders [<A
|
||||
HREF="bibliography.html#jaakko_tuple_assign">1</A>].
|
||||
|
||||
<P>
|
||||
|
||||
<H3>Where Defined</H3>
|
||||
|
||||
<P>
|
||||
<a href="../../boost/utility.hpp"><TT>boost/utility.hpp</TT></a>
|
||||
|
||||
<P>
|
||||
|
||||
<H3>Example</H3>
|
||||
|
||||
<P>
|
||||
An example of using the <TT>tie()</TT> function with the
|
||||
<TT>vertices()</TT> function, which returns a pair of
|
||||
type <TT>std::pair<vertex_iterator,vertex_iterator></TT>. The
|
||||
pair of iterators is assigned to the iterator variables <TT>i</TT> and
|
||||
<TT>end</TT>.
|
||||
|
||||
<P>
|
||||
<PRE>
|
||||
graph_traits< adjacency_list<> >::vertex_iterator i, end;
|
||||
for(tie(i,end) = vertices(G); i != end; ++i)
|
||||
// ...
|
||||
</PRE>
|
||||
|
||||
<P>
|
||||
Here is another example that uses <TT>tie()</TT> for handling
|
||||
operaitons with <a
|
||||
href="http://www.sgi.com/Technology/STL/set.html"><TT>std::set</TT></a>.
|
||||
|
||||
<P>
|
||||
<PRE>
|
||||
#include <set>
|
||||
#include <algorithm>
|
||||
#include <iostream>
|
||||
#include <boost/utility.hpp>
|
||||
|
||||
int
|
||||
main(int, char*[])
|
||||
{
|
||||
{
|
||||
typedef std::set<int> SetT;
|
||||
SetT::iterator i, end;
|
||||
bool inserted;
|
||||
|
||||
int vals[5] = { 5, 2, 4, 9, 1 };
|
||||
SetT s(vals, vals + 5);
|
||||
|
||||
// Using tie() with a return value of pair<iterator,bool>
|
||||
|
||||
int new_vals[2] = { 3, 9 };
|
||||
|
||||
for (int k = 0; k < 2; ++k) {
|
||||
boost::tie(i,inserted) = s.insert(new_vals[k]);
|
||||
if (!inserted)
|
||||
std::cout << *i << " was already in the set." << std::endl;
|
||||
else
|
||||
std::cout << *i << " successfully inserted." << std::endl;
|
||||
}
|
||||
}
|
||||
{
|
||||
int* i, *end;
|
||||
int vals[6] = { 5, 2, 4, 4, 9, 1 };
|
||||
std::sort(vals, vals + 6);
|
||||
|
||||
// Using tie() with a return value of pair<iterator,iterator>
|
||||
|
||||
boost::tie(i,end) = std::equal_range(vals, vals + 6, 4);
|
||||
std::cout << "There were " << std::distance(i,end)
|
||||
<< " occurances of " << *i << "." << std::endl;
|
||||
// Footnote: of course one would normally just use std::count()
|
||||
// to get this information, but that would spoil the example :)
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
</PRE>
|
||||
The output is:
|
||||
<PRE>
|
||||
3 successfully inserted.
|
||||
9 was already in the set.
|
||||
There were 2 occurances of 4.
|
||||
</PRE>
|
||||
|
||||
<br>
|
||||
<HR>
|
||||
<TABLE>
|
||||
<TR valign=top>
|
||||
<TD nowrap>Copyright © 2000</TD><TD>
|
||||
<A HREF=http://www.boost.org/people/jeremy_siek.htm>Jeremy Siek</A>,
|
||||
Univ.of Notre Dame (<A
|
||||
HREF="mailto:jsiek@lsc.nd.edu">jsiek@lsc.nd.edu</A>)<br>
|
||||
<A HREF=http://www.lsc.nd.edu/~llee1>Lie-Quan Lee</A>, Univ.of Notre Dame (<A HREF="mailto:llee1@lsc.nd.edu">llee1@lsc.nd.edu</A>)<br>
|
||||
<A HREF=http://www.lsc.nd.edu/~lums>Andrew Lumsdaine</A>,
|
||||
Univ.of Notre Dame (<A
|
||||
HREF="mailto:lums@lsc.nd.edu">lums@lsc.nd.edu</A>)
|
||||
</TD></TR></TABLE>
|
||||
|
||||
</BODY>
|
||||
</HTML>
|
61
tie_example.cpp
Normal file
61
tie_example.cpp
Normal file
@ -0,0 +1,61 @@
|
||||
// (C) Copyright Jeremy Siek 2000. 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.
|
||||
//
|
||||
// This is an example demonstrating how to use the tie() function.
|
||||
// The purpose of tie() is to make it easiery to deal with std::pair
|
||||
// return values.
|
||||
//
|
||||
// Contributed by Jeremy Siek
|
||||
//
|
||||
// Sample output
|
||||
//
|
||||
// 3 successfully inserted.
|
||||
// 9 was already in the set.
|
||||
// There were 2 occurances of 4.
|
||||
|
||||
#include <set>
|
||||
#include <algorithm>
|
||||
#include <iostream>
|
||||
#include <boost/utility.hpp>
|
||||
|
||||
int
|
||||
main(int, char*[])
|
||||
{
|
||||
{
|
||||
typedef std::set<int> SetT;
|
||||
SetT::iterator i, end;
|
||||
bool inserted;
|
||||
|
||||
int vals[5] = { 5, 2, 4, 9, 1 };
|
||||
SetT s(vals, vals + 5);
|
||||
|
||||
// Using tie() with a return value of pair<iterator,bool>
|
||||
|
||||
int new_vals[2] = { 3, 9 };
|
||||
|
||||
for (int k = 0; k < 2; ++k) {
|
||||
boost::tie(i,inserted) = s.insert(new_vals[k]);
|
||||
if (!inserted)
|
||||
std::cout << *i << " was already in the set." << std::endl;
|
||||
else
|
||||
std::cout << *i << " successfully inserted." << std::endl;
|
||||
}
|
||||
}
|
||||
{
|
||||
int* i, *end;
|
||||
int vals[6] = { 5, 2, 4, 4, 9, 1 };
|
||||
std::sort(vals, vals + 6);
|
||||
|
||||
// Using tie() with a return value of pair<iterator,iterator>
|
||||
|
||||
boost::tie(i,end) = std::equal_range(vals, vals + 6, 4);
|
||||
std::cout << "There were " << std::distance(i,end)
|
||||
<< " occurances of " << *i << "." << std::endl;
|
||||
// Footnote: of course one would normally just use std::count()
|
||||
// to get this information, but that would spoil the example :)
|
||||
}
|
||||
return 0;
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user