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