forked from boostorg/utility
edits. What can I say?
[SVN r10992]
This commit is contained in:
@@ -115,8 +115,8 @@ on other iterators (adapted iterators) and generators of new iterator
|
|||||||
families (iterator adaptors). The Iterator Adaptor Library is an
|
families (iterator adaptors). The Iterator Adaptor Library is an
|
||||||
example of policy-based design and employs template
|
example of policy-based design and employs template
|
||||||
meta-programming. We also present the Policy Adapter implementation
|
meta-programming. We also present the Policy Adapter implementation
|
||||||
pattern, a strategy used by the library that can also be used to
|
pattern, a strategy which can also be used to generate new
|
||||||
generate new representatives of other abstract Concept families.
|
representatives of other abstract Concept families.
|
||||||
\end{abstract}
|
\end{abstract}
|
||||||
|
|
||||||
|
|
||||||
@@ -152,14 +152,17 @@ Concept, iterators can be both efficient and convenient to use.
|
|||||||
|
|
||||||
The \Cpp\ Standard Library contains a wide variety of useful
|
The \Cpp\ Standard Library contains a wide variety of useful
|
||||||
iterators. Every one of the standard containers comes with constant
|
iterators. Every one of the standard containers comes with constant
|
||||||
and mutable iterators (iterators that point to constant objects and
|
and mutable iterators\footnote{The term \emph{mutable iterator} refers
|
||||||
iterators that point to objects that can be changed or assigned to),
|
to iterators over objects that can be changed by assigning to the
|
||||||
and also \code{reverse\_} versions of the iterators that traverse the
|
dereferenced iterator, while \emph{constant iterator} refers to
|
||||||
|
iterators over objects that cannot be modified}, and also
|
||||||
|
\code{reverse\_} versions of those same iterators which traverse the
|
||||||
container in the opposite direction. The Standard also supplies
|
container in the opposite direction. The Standard also supplies
|
||||||
\code{istream\_\-iterator} and \code{ostream\_\-iterator} for reading
|
\code{istream\_\-iterator} and \code{ostream\_\-iterator} for reading
|
||||||
from and writing to streams, \code{insert\_iterator} and
|
from and writing to streams, \code{insert\_iterator},
|
||||||
\code{back\_insert\_iterator} for inserting elements in containers,
|
\code{front\_insert\_iterator} and \code{back\_insert\_iterator} for
|
||||||
and \code{raw\_\-storage\_\-iterator} for initializing raw
|
inserting elements into containers, and
|
||||||
|
\code{raw\_\-storage\_\-iterator} for initializing raw
|
||||||
memory~\cite{iso98:_cpp_final_draft_standard}.
|
memory~\cite{iso98:_cpp_final_draft_standard}.
|
||||||
|
|
||||||
Despite the many iterators supplied by the Standard Library, many
|
Despite the many iterators supplied by the Standard Library, many
|
||||||
@@ -169,7 +172,7 @@ several of these, for example
|
|||||||
\code{line\_iterator}~\cite{austern99:_gener_progr_stl}
|
\code{line\_iterator}~\cite{austern99:_gener_progr_stl}
|
||||||
\code{Constant\_iterator}~\cite{koenig97:_rumin_cpp}. The iterator
|
\code{Constant\_iterator}~\cite{koenig97:_rumin_cpp}. The iterator
|
||||||
abstraction is so powerful, however, that we expect programmers will
|
abstraction is so powerful, however, that we expect programmers will
|
||||||
always invent new iterator types.
|
always need to invent new iterator types.
|
||||||
|
|
||||||
\subsection{Adaptors}
|
\subsection{Adaptors}
|
||||||
|
|
||||||
@@ -191,8 +194,8 @@ 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_iterators}
|
||||||
which 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.
|
||||||
|
|
||||||
@@ -235,7 +238,7 @@ have followed the lead of the standard library, which provides a
|
|||||||
\code{base()} function to access the underlying iterator object of a
|
\code{base()} function to access the underlying iterator object of a
|
||||||
\reverseiterator\ adaptor.}
|
\reverseiterator\ adaptor.}
|
||||||
|
|
||||||
\subsection{Core Elements of the 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 is to identify
|
||||||
the core elements of its interface. We have identified the following
|
the core elements of its interface. We have identified the following
|
||||||
@@ -286,8 +289,9 @@ were quickly implemented using \iteratoradaptor{}:\begin{itemize}
|
|||||||
smart pointers and applies an extra level of dereferencing.
|
smart pointers and applies an extra level of dereferencing.
|
||||||
|
|
||||||
\item Reverse Iterator Adaptor, which inverts the direction of a
|
\item Reverse Iterator Adaptor, which inverts the direction of a
|
||||||
\code{Base} iterator's motion.
|
\code{Base} iterator's motion, while allowing adapted constant and
|
||||||
% say something about how this one is better than the std one?
|
mutable iterators to interact in the expected ways. We will discuss
|
||||||
|
this further in Section \ref{sec:constant-mutable-iterations}.
|
||||||
|
|
||||||
\item Transform Iterator Adaptor, which applies a user-defined
|
\item Transform Iterator Adaptor, which applies a user-defined
|
||||||
function object to the underlying values when dereferenced. We will
|
function object to the underlying values when dereferenced. We will
|
||||||
@@ -328,7 +332,7 @@ and delegating functions and by taking care of the complex details of
|
|||||||
iterator implementation.
|
iterator implementation.
|
||||||
|
|
||||||
The central design feature of \iteratoradaptor\ is parameterization by
|
The central design feature of \iteratoradaptor\ is parameterization by
|
||||||
an iterator policies class. The policies class is the primary
|
a policies class. The policies class is the primary
|
||||||
communication mechanism between the iterator implementer and the
|
communication mechanism between the iterator implementer and the
|
||||||
\iteratoradaptor{}; it specifies how the new iterator type
|
\iteratoradaptor{}; it specifies how the new iterator type
|
||||||
behaves. Unlike the policy classes
|
behaves. Unlike the policy classes
|
||||||
@@ -339,12 +343,18 @@ implementation.
|
|||||||
\subsection{Iterator Policies Class}
|
\subsection{Iterator Policies Class}
|
||||||
\label{sec:iterator-policies-class}
|
\label{sec:iterator-policies-class}
|
||||||
|
|
||||||
The following example shows how to implement the policies class for a transform
|
The following example shows how to implement the policies class for a
|
||||||
iterator adaptor: an iterator that applies some function to the value returned
|
transform iterator adaptor: an iterator that applies some function to
|
||||||
by dereferencing the base iterator. The
|
the value returned by dereferencing the base iterator. The
|
||||||
\code{transform\_\-iterator\_\-policies} class is templated on the function
|
\code{transform\_\-iterator\_\-policies} class is templated on the
|
||||||
object type, and a function object is stored as a data member of the policies
|
function object type, and a function object is stored as a data member
|
||||||
class. When adapting an underlying iterator, it is easiest to store any extra state
|
of the policies class.\footnote{We might instead have composed the
|
||||||
|
underlying iterator and the function object into a single \code{Base}
|
||||||
|
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
|
needed by the resulting adapted iterator in the policies class rather than
|
||||||
incorporating it into the \code{Base} type because \iteratoradaptor\
|
incorporating it into the \code{Base} type because \iteratoradaptor\
|
||||||
provides so many useful defaults when the \code{Base} type is an iterator.
|
provides so many useful defaults when the \code{Base} type is an iterator.
|
||||||
@@ -357,11 +367,12 @@ operations to the base iterator. The main event of the
|
|||||||
\code{transform\_\-iterator\_\-policies} class is the
|
\code{transform\_\-iterator\_\-policies} class is the
|
||||||
\code{dereference()} member function, which simply applies the
|
\code{dereference()} member function, which simply applies the
|
||||||
function to the dereferenced value. The base iterator object is the
|
function to the dereferenced value. The base iterator object is the
|
||||||
second argument to the \code{dereference()} function. The iterator
|
second argument to the \code{dereference()} function. Because the
|
||||||
type is a template parameter to allow this policy class to be used
|
iterator type is a template parameter of the \code{dereference()}
|
||||||
with any base iterator type.\footnote{The term``\code{BaseIterator}''
|
function, the same concrete policies class can be used with any base
|
||||||
here is meant to denote that the \code{Base} type is expected to be an
|
iterator type, which greatly simplifies adaptation.\footnote{The
|
||||||
iterator.}
|
term``\code{BaseIterator}'' here is meant to denote that the
|
||||||
|
\code{Base} type is expected to be an iterator.}
|
||||||
|
|
||||||
{\footnotesize
|
{\footnotesize
|
||||||
\begin{verbatim}
|
\begin{verbatim}
|
||||||
@@ -460,10 +471,10 @@ namespace boost {
|
|||||||
\label{sec:iter-type-generator}
|
\label{sec:iter-type-generator}
|
||||||
|
|
||||||
In Section~\ref{sec:iterator-policies-class} we showed how to create
|
In Section~\ref{sec:iterator-policies-class} we showed how to create
|
||||||
the policy class for the transform iterator, so the next step is to
|
the policy class for the transform iterator; the next step is to use
|
||||||
use the \iteratoradaptor\ template to construct the actual iterator
|
the \iteratoradaptor\ template to construct the actual iterator
|
||||||
type. The best way to package the construction of the transform
|
type. The best way to package the construction of the transform
|
||||||
iterator is to create a \emph{type generator}, which is a class
|
iterator is to create a \emph{type generator}: a class
|
||||||
template whose sole purpose is to simplify the instantiation of some
|
template whose sole purpose is to simplify the instantiation of some
|
||||||
other complicated class template. It fulfills the same need as a
|
other complicated class template. It fulfills the same need as a
|
||||||
template typedef would if that were part of the \Cpp\ language. The
|
template typedef would if that were part of the \Cpp\ language. The
|
||||||
@@ -486,11 +497,11 @@ shows the type generator for the transform iterator.
|
|||||||
\end{verbatim}
|
\end{verbatim}
|
||||||
}
|
}
|
||||||
|
|
||||||
We use \iteratoradaptor\ to define the transform iterator type
|
We use \iteratoradaptor\ to define the transform iterator type as a
|
||||||
as a nested \code{typedef} inside the
|
nested \code{typedef} inside the
|
||||||
\code{transform\_\-iterator\_\-generator} class. The first parameter
|
\code{transform\_\-iterator\_\-generator} class. The first parameter
|
||||||
to \iteratoradaptor\ is the base iterator type and the second
|
to \iteratoradaptor\ is the base iterator type and the second is the
|
||||||
is the policies class. The remaining parameters specify the iterators
|
policies class. The remaining parameters specify the iterator's
|
||||||
associated types and are given as \emph{named parameters}. We will
|
associated types and are given as \emph{named parameters}. We will
|
||||||
discuss this technique in \S\ref{sec:named-template-parameters}.
|
discuss this technique in \S\ref{sec:named-template-parameters}.
|
||||||
|
|
||||||
@@ -503,11 +514,11 @@ the \code{pointer} type defaults to \code{value\_type*} and the
|
|||||||
\differencetype{} defaults to the \differencetype{} of
|
\differencetype{} defaults to the \differencetype{} of
|
||||||
the base iterator.
|
the base iterator.
|
||||||
|
|
||||||
It is tempting to create a \code{transform\_\-iterator} by deriving
|
It is tempting to create a \code{transform\_\-iterator} class template
|
||||||
from \iteratoradaptor\ (as an alternative to using the
|
which is derived from \iteratoradaptor\, instead of using the
|
||||||
generator). This approach does not work, for example, because the
|
generator. This approach does not work, for example, because the
|
||||||
return type of \code{operator++} of an iterator is required to be the
|
return type of \code{operator++} of an iterator is required to be the
|
||||||
same iterator type, but in this case the return type would be
|
same iterator type, while in this case the return type would be
|
||||||
\iteratoradaptor\ and not \code{transform\_\-iterator}.
|
\iteratoradaptor\ and not \code{transform\_\-iterator}.
|
||||||
|
|
||||||
%It
|
%It
|
||||||
@@ -532,14 +543,15 @@ they would have to separately construct a policies object and then the
|
|||||||
iterator object. We therefore recommend that iterator implementers
|
iterator object. We therefore recommend that iterator implementers
|
||||||
create an \emph{object generator} function for their iterator. The
|
create an \emph{object generator} function for their iterator. The
|
||||||
following is the generator function for the transform iterator
|
following is the generator function for the transform iterator
|
||||||
adaptor.\footnote{
|
adaptor.\footnote{ Although there is precedent in the standard for
|
||||||
There is precedent in the standard for calling such
|
calling such an object generator, simply
|
||||||
an object generator, simply ``\code{transform\_iterator()}''
|
``\code{transform\_iterator()}'' (e.g. \code{std::back\_inserter}),
|
||||||
(e.g. \code{std::back\_inserter}), but also for the more explicit
|
the standard also uses the more explicit ``\code{make\_}'' prefix
|
||||||
\code{make\_} prefix (e.g. \code{std::make\_pair()}) and occasionally
|
(e.g. \code{std::make\_pair()}) and occasionally also uses the simple
|
||||||
for using the simple name for the adaptor type itself
|
name for the iterator type itself
|
||||||
(e.g. \code{std::reverse\_iterator}). In the end, the authors decided
|
(e.g. \code{std::reverse\_iterator}). In the end, the authors felt
|
||||||
that explicit was better than implicit. }
|
that explicit was better than implicit and decided to use the
|
||||||
|
``\code{make\_}'' prefix for object generators. }
|
||||||
|
|
||||||
{\footnotesize
|
{\footnotesize
|
||||||
\begin{verbatim}
|
\begin{verbatim}
|
||||||
@@ -714,7 +726,7 @@ iterator takes its \valuetype\ from the \code{Base}
|
|||||||
iterator's \iteratortraits{}. However, if the \code{Value} parameter \emph{is} supplied,
|
iterator's \iteratortraits{}. However, if the \code{Value} parameter \emph{is} supplied,
|
||||||
an adjustment is made which allows the user to more easily create a
|
an adjustment is made which allows the user to more easily create a
|
||||||
constant iterator: if the \code{Value} parameter is \code{const T},
|
constant iterator: if the \code{Value} parameter is \code{const T},
|
||||||
the \valuetype\ will just be \code{T}.Perhaps
|
the \valuetype\ will just be \code{T}. Perhaps
|
||||||
strangely, a constant iterator's \valuetype\ should never be
|
strangely, a constant iterator's \valuetype\ should never be
|
||||||
\code{const}, because it would prevent algorithms from declaring
|
\code{const}, because it would prevent algorithms from declaring
|
||||||
modifiable temporary objects which are copied from dereferenced
|
modifiable temporary objects which are copied from dereferenced
|
||||||
@@ -812,8 +824,7 @@ associated types used to look something like this:
|
|||||||
Unfortunately, this strategy can only take us so far. It turns out
|
Unfortunately, this strategy can only take us so far. It turns out
|
||||||
that there are plenty of iterators which don't fit neatly into the
|
that there are plenty of iterators which don't fit neatly into the
|
||||||
system for ordering defaults. For example, the specialized Transform
|
system for ordering defaults. For example, the specialized Transform
|
||||||
Iterator Adaptor described earlier
|
Iterator Adaptor described in Section~\ref{sec:iterator-policies-class}
|
||||||
% When we reorganize the paper it may appear later. check this out.
|
|
||||||
limits the category of its \code{Base} iterator to
|
limits the category of its \code{Base} iterator to
|
||||||
\stlconcept{InputIterator}, so the we'd only need to supply the
|
\stlconcept{InputIterator}, so the we'd only need to supply the
|
||||||
\valuetype{}, \code{reference}, and \iteratorcategory\ if
|
\valuetype{}, \code{reference}, and \iteratorcategory\ if
|
||||||
@@ -840,7 +851,7 @@ an appropriately-named wrapper class for each parameter. For example:
|
|||||||
}
|
}
|
||||||
|
|
||||||
Instead of passing the argument \code{Value} directly to
|
Instead of passing the argument \code{Value} directly to
|
||||||
\iteratoradaptor\ the user passes
|
\iteratoradaptor\ the user can pass
|
||||||
\code{value\_type\_is<Value>}. The \iteratoradaptor\ has
|
\code{value\_type\_is<Value>}. The \iteratoradaptor\ has
|
||||||
five arguments for the associated types, each of which could be used
|
five arguments for the associated types, each of which could be used
|
||||||
to specify any of the actual parameters. The
|
to specify any of the actual parameters. The
|
||||||
@@ -967,7 +978,9 @@ kinds of iterators should propagate the ability to interact. For
|
|||||||
example, a reverse iterator adaptor applied to \code{C::iterator} and
|
example, a reverse iterator adaptor applied to \code{C::iterator} and
|
||||||
\code{C::const\_iterator} should result in mutable and constant
|
\code{C::const\_iterator} should result in mutable and constant
|
||||||
reverse iterator types that have the same ability to interact as the
|
reverse iterator types that have the same ability to interact as the
|
||||||
\code{Base} iterators do.
|
\code{Base} iterators do. The \reverseiterator{} adaptor supplied by
|
||||||
|
the Iterator Adaptor Library have this ability, although those
|
||||||
|
supplied by the \Cpp\ standard library do not.
|
||||||
|
|
||||||
The iterator adaptor binary operators are implemented using function
|
The iterator adaptor binary operators are implemented using function
|
||||||
templates (as shown in the previous Subsection). This allows the same
|
templates (as shown in the previous Subsection). This allows the same
|
||||||
@@ -1117,13 +1130,13 @@ dangling reference.
|
|||||||
|
|
||||||
The \Cpp\ Standard specifies that the return type of \code{operator[]}
|
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-balue from \code{operator[]}
|
opens up the possibility of returning by-value from \code{operator[]}
|
||||||
instead of by-reference, and 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 a less
|
||||||
orthogonal design since \code{operator*} is required to return the
|
orthogonal design since \code{operator*} is required to return the
|
||||||
exact type \code{T\&}, and one might think that \code{operator[]} and
|
exact type \code{T\&}, and one might think that \code{operator[]} and
|
||||||
\code{operator*} should be same in this respect. The \Cpp\ Standards
|
\code{operator*} should be same in this respect. The \Cpp\ Standards
|
||||||
Committee is currently debating as to whether the random access
|
Committee is currently debating the question of whether the random access
|
||||||
iterator requirements should be changed.
|
iterator 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
|
||||||
@@ -1143,9 +1156,11 @@ Under the current \Cpp\ Standard, you cannot assign into the result of
|
|||||||
but instead must write \code{*(i + n) = x}.
|
but instead must write \code{*(i + n) = x}.
|
||||||
|
|
||||||
It would be nice to return by-reference for iterators that can support
|
It would be nice to return by-reference for iterators that can support
|
||||||
it, and by-value for the rest. However, the current
|
it, and by-value for the rest. However, the current \iteratortraits\
|
||||||
\iteratortraits\ does not provide enough information to make the
|
does not provide enough information to make the choice. The proposal
|
||||||
choice.
|
in~\cite{siek01:_improved_iter_cat} would solve this problem, but of
|
||||||
|
course that will take some time to gain acceptance.
|
||||||
|
|
||||||
|
|
||||||
% Jeremy: I didn't agree with this part, so commented it out
|
% Jeremy: I didn't agree with this part, so commented it out
|
||||||
% temporarily. I think an iterator which can return by-reference for
|
% temporarily. I think an iterator which can return by-reference for
|
||||||
@@ -1157,10 +1172,6 @@ choice.
|
|||||||
% iterator would either return by-value for both \code{operator*} and
|
% iterator would either return by-value for both \code{operator*} and
|
||||||
% \code{operator[]} or return by-reference for both.
|
% \code{operator[]} or return by-reference for both.
|
||||||
|
|
||||||
The proposal in~\cite{siek01:_improved_iter_cat} would solve this
|
|
||||||
problem, but of course that will take some time to gain acceptance.
|
|
||||||
|
|
||||||
|
|
||||||
\section{Conclusion}
|
\section{Conclusion}
|
||||||
|
|
||||||
Constructing iterators and iterator adaptors is a common task for
|
Constructing iterators and iterator adaptors is a common task for
|
||||||
|
Reference in New Issue
Block a user