forked from boostorg/utility
some edits
[SVN r10993]
This commit is contained in:
@ -89,7 +89,8 @@
|
||||
|
||||
\title{Generating Iterator Types}
|
||||
|
||||
\author{David Abrahams$^\dag$ and Jeremy Siek$^\ddag$ \\
|
||||
\author{David Abrahams$^\dag$ and Jeremy Siek$^\ddag$\thanks{This work
|
||||
was partially supported by NSF grant ACI-9982205.} \\
|
||||
\\
|
||||
$^\dag$ Altra Broadband \\
|
||||
\texttt{abrahams@altrabroadband.com}\\
|
||||
@ -194,7 +195,7 @@ bounds-checking to an existing iterator.
|
||||
Library~\cite{TMPW00:Weiser}, which adapts containers, are themselves
|
||||
adaptors over the underlying iterators.
|
||||
|
||||
\item smart iterators~\cite{becker98:_smart_iterators}
|
||||
\item smart iterators~\cite{becker98:_smart_iteraters}
|
||||
adapt an iterator's dereferencing behavior by applying a
|
||||
function object to the object being referenced and returning the
|
||||
result.
|
||||
@ -203,13 +204,18 @@ result.
|
||||
in which a variety of adaptor types are enumerated.
|
||||
|
||||
% Jeremy, I don't know what to say about these two. Can you fill it in?
|
||||
\item compound iterators~\cite{alexandrescu98:_compound_iters}
|
||||
\item compound iterators~\cite{alexandrescu98:_compound_iters},
|
||||
which access a slice out of a container of containers.
|
||||
|
||||
\item Several iterators from the MTL~\cite{siek99:_scitools}.
|
||||
\item Several iterator adaptors from the MTL~\cite{siek99:_scitools}.
|
||||
The MTL contains a strided iterator, where each call to \code{operator++()}
|
||||
moved the iterator ahead by some constant factor, and a
|
||||
scaled iterator which multiplies the dereferenced value by some
|
||||
constant.
|
||||
|
||||
\end{itemize}
|
||||
|
||||
\section{The Boost Iterator Adaptor Library}
|
||||
\section{The Design of the Boost Iterator Adaptor Library}
|
||||
|
||||
% We need an intro here (do we?), but I don't think the text below
|
||||
% fits in. Suggestions?
|
||||
@ -223,7 +229,7 @@ in which a variety of adaptor types are enumerated.
|
||||
% fact that most iterators are conceptually simple. The Boost Iterator
|
||||
% Adaptor Library addresses these problems.
|
||||
|
||||
\subsection{Overall Design}
|
||||
%\subsection{Overall Design}
|
||||
|
||||
To automate the repetitive work of constructing iterators, one would
|
||||
need a generator of new iterator types that can accommodate all the
|
||||
@ -240,16 +246,17 @@ have followed the lead of the standard library, which provides a
|
||||
|
||||
\subsection{Core Elements of the Iterator Concept}
|
||||
|
||||
The first step in designing such a generalized Model is to identify
|
||||
the core elements of its interface. We have identified the following
|
||||
core behaviors for iterators:\begin{itemize}
|
||||
The first step in designing such a generalized model of the iterator
|
||||
concept is to identify the core elements of its interface. We have
|
||||
identified the following core behaviors for iterators:
|
||||
\begin{itemize}
|
||||
\item dereferencing
|
||||
\item incrementing
|
||||
\item decrementing
|
||||
\item equality comparison
|
||||
\item random-access motion
|
||||
\item distance measurement
|
||||
\item ordered comparison
|
||||
%% \item ordered comparison
|
||||
%% Yikes, Jeremy! I think that including both less and distance in the
|
||||
%% design might be a design mistake. Doesn't that introduce redundancy?
|
||||
%% Shouldn't operator<() be implemented in terms of distance?
|
||||
@ -354,12 +361,13 @@ type, but that would have been much more work because so many useful
|
||||
defaults are provided when the \code{Base} type is itself an
|
||||
iterator.}
|
||||
|
||||
When adapting an underlying iterator, it is easiest to store any extra state
|
||||
needed by the resulting adapted iterator in the policies class rather than
|
||||
incorporating it into the \code{Base} type because \iteratoradaptor\
|
||||
provides so many useful defaults when the \code{Base} type is an iterator.
|
||||
% this last sentence may need more explaining, I didn't get it on the
|
||||
% first read through. -JGS
|
||||
When adapting an underlying iterator, it is easiest to store any extra
|
||||
state needed by the resulting iterator in the policies class. The
|
||||
alternative is to wrap the underlying iterator in another class that
|
||||
contains the state, thereby incorporating the state into the
|
||||
\code{Base} type. This approach is much more work since the wrapping
|
||||
class will have to delegate lots of operations (instead of allowing
|
||||
the \iteratoradaptor\ to implement the delegations).
|
||||
|
||||
The policies class inherits from
|
||||
\code{default\_\-iterator\_\-policies}, which delegates all other
|
||||
@ -529,8 +537,8 @@ same iterator type, while in this case the return type would be
|
||||
\label{sec:iter-object-generator}
|
||||
|
||||
The next question is how users of the transform iterator will
|
||||
construct the iterator. The \iteratoradaptor\ class has the
|
||||
following constructor.
|
||||
construct the iterator. The \iteratoradaptor\o class has the following
|
||||
constructor.
|
||||
|
||||
{\footnotesize
|
||||
\begin{verbatim}
|
||||
@ -538,17 +546,31 @@ following constructor.
|
||||
\end{verbatim}
|
||||
}
|
||||
|
||||
It would be cumbersome for the user to call this constructor since
|
||||
they would have to separately construct a policies object and then the
|
||||
iterator object. We therefore recommend that iterator implementers
|
||||
create an \emph{object generator} function for their iterator. The
|
||||
following is the generator function for the transform iterator
|
||||
adaptor.\footnote{ Although there is precedent in the standard for
|
||||
calling such an object generator, simply
|
||||
``\code{transform\_iterator()}'' (e.g. \code{std::back\_inserter}),
|
||||
the standard also uses the more explicit ``\code{make\_}'' prefix
|
||||
(e.g. \code{std::make\_pair()}) and occasionally also uses the simple
|
||||
name for the iterator type itself
|
||||
There are two reasons why it is cumbersome for the user to use this
|
||||
constructor. First, to call the constructor the user needs to write
|
||||
down the exact type of the iterator adaptor. Writing down the type is
|
||||
complex, and often requires an extra line of code. If instead we
|
||||
provide an \emph{object generator} function, the type of the iterator
|
||||
adaptor need not be written down explicitly by the user. The
|
||||
generator function deduces the type of the iterator adaptor and
|
||||
returns the new iterator adaptor object, which can then be passed
|
||||
directly to the function operating on the iterator.
|
||||
|
||||
The second reason it is cumbersome, in this case, to use the
|
||||
\iteratoradaptor\ constructor, is that the policies object has to be
|
||||
explicitly constructed and passed to the iterator object. For a
|
||||
transform iterator it would be nicer to create the new iterator based
|
||||
on the adapted iterator and the function object, thereby not exposing
|
||||
the policies class to the user.
|
||||
|
||||
We therefore recommend that iterator implementers create an
|
||||
\emph{object generator} function for their iterator. The following is
|
||||
the generator function for the transform iterator adaptor.\footnote{
|
||||
Although there is precedent in the standard for calling such an object
|
||||
generator, simply ``\code{transform\_iterator()}''
|
||||
(e.g. \code{std::back\_inserter}), the standard also uses the more
|
||||
explicit ``\code{make\_}'' prefix (e.g. \code{std::make\_pair()}) and
|
||||
occasionally also uses the simple name for the iterator type itself
|
||||
(e.g. \code{std::reverse\_iterator}). In the end, the authors felt
|
||||
that explicit was better than implicit and decided to use the
|
||||
``\code{make\_}'' prefix for object generators. }
|
||||
@ -992,8 +1014,8 @@ combinations of constant and mutable iterator interaction.
|
||||
|
||||
Most of the redundant operators are implemented in a straightforward
|
||||
way based on the core operators. For example, the \code{operator+} is
|
||||
implemented in terms of \code{operator+=}. There are a total of 7 core
|
||||
operators and 10 redundant operators.
|
||||
implemented in terms of \code{operator+=}. There are a total of 6 core
|
||||
operators and 11 redundant operators.
|
||||
|
||||
{\footnotesize
|
||||
\begin{verbatim}
|
||||
@ -1082,14 +1104,11 @@ iterator categories derived from the standard ones.
|
||||
\label{sec:op-bracket-impl}
|
||||
|
||||
The implementation of \code{operator[]} would be trivial except for
|
||||
the issue surrounding what the return type should be, whether the
|
||||
return type should be by-reference or by-value.
|
||||
|
||||
It is dangerous to make the \iteratoradaptor\ always return a
|
||||
reference for \code{operator[]} for there are certain situations in
|
||||
which this can cause run-time errors. Suppose the base iterator is
|
||||
reading in elements from a file and caching each element as a data
|
||||
member of the iterator.
|
||||
the question of whether it should return a reference or a
|
||||
value. Although it would be more useful to return a reference, this
|
||||
can cause run-time errors when adapting a certain class of legal base
|
||||
iterators. Suppose the base iterator is reading in elements from a
|
||||
file and caching each element as a data member of the iterator.
|
||||
|
||||
{\footnotesize
|
||||
\begin{verbatim}
|
||||
@ -1132,12 +1151,12 @@ The \Cpp\ Standard specifies that the return type of \code{operator[]}
|
||||
of a random access iterator must be ``convertible to \code{T}''. This
|
||||
opens up the possibility of returning by-value from \code{operator[]}
|
||||
instead of by-reference, thereby avoiding the above problem. This
|
||||
approach, though safer, has the disadvantage of being a less
|
||||
orthogonal design since \code{operator*} is required to return the
|
||||
exact type \code{T\&}, and one might think that \code{operator[]} and
|
||||
\code{operator*} should be same in this respect. The \Cpp\ Standards
|
||||
Committee is currently debating the question of whether the random access
|
||||
iterator requirements should be changed.
|
||||
approach, though safer, has the disadvantage of being unintuitive
|
||||
since \code{operator*} is required to return the exact type \code{T\&}
|
||||
and one might expect that \code{operator[]} and \code{operator*} would
|
||||
be same in this respect. The \Cpp\ Standards Committee is currently
|
||||
debating the question of whether the random access iterator
|
||||
requirements should be changed.
|
||||
|
||||
Boost's \iteratoradaptor\ takes the safe route and returns the result
|
||||
by-value. This meets the random access iterator requirements of the
|
||||
|
Reference in New Issue
Block a user