diff --git a/doc/BidirectionalTraversal.html b/doc/BidirectionalTraversal.html index 5bc8342..9c45f40 100644 --- a/doc/BidirectionalTraversal.html +++ b/doc/BidirectionalTraversal.html @@ -3,295 +3,14 @@
- +Table of Contents
The Incrementable argument shall be Copy Constructible and Assignable.
If iterator_category is convertible to forward_iterator_tag or forward_traversal_tag, the following must be well-formed:
@@ -429,8 +147,8 @@ n = i - j; i < j;Specializations of counting_iterator model Readable Lvalue Iterator. In addition, they model the concepts corresponding to the iterator tags to which their iterator_category is convertible. @@ -445,8 +163,8 @@ concepts modeled by Incrementable counting_iterator<Y,C2,D2> if and only if X is interoperable with Y.
In addition to the operations required by the concepts modeled by counting_iterator, counting_iterator provides the following operations.
@@ -539,8 +257,8 @@ with current construcThis example fills an array with numbers and a second array with pointers into the first array, using counting_iterator for both tasks. Finally indirect_iterator is used to print out the numbers @@ -570,8 +288,14 @@ std::cout << std::endl; indirectly printing out the numbers from 0 to 7 0 1 2 3 4 5 6 -
The source code for this example can be found here.
+The source code for this example can be found here.
Table of Contents
Iterators play an important role in modern C++ programming. The iterator is the central abstraction of the algorithms of the Standard Library, allowing algorithms to be re-used in in a wide variety of contexts. The C++ Standard Library contains a wide variety of useful iterators. Every one of the standard containers comes with constant -and mutable iterators [2], and also reverse versions of those +and mutable iterators2, and also reverse versions of those same iterators which traverse the container in the opposite direction. The Standard also supplies istream_iterator and ostream_iterator for reading from and writing to streams, @@ -486,7 +204,7 @@ multiplies the dereferenced value by some constant.
[1] | We use the term concept to mean a set of requirements + |
[1] | We use the term concept to mean a set of requirements that a type must satisfy to be used with a particular template parameter. |
[2] | The term mutable iterator refers to iterators over objects that + |
[2] | The term mutable iterator refers to iterators over objects that can be changed by assigning to the dereferenced iterator, while constant iterator refers to iterators over objects that cannot be modified. |
[Cop95] | [Coplien, 1995] Coplien, J., Curiously Recurring Template + |
[Cop95] | [Coplien, 1995] Coplien, J., Curiously Recurring Template Patterns, C++ Report, February 1995, pp. 24-27. |
The iterator_adaptor class template adapts some Base [3] +
The iterator_adaptor class template adapts some Base3 type to create a new iterator. Instantiations of iterator_adaptor are derived from a corresponding instantiation of iterator_facade and implement the core behaviors in terms of the Base type. In @@ -755,7 +473,7 @@ instance of the Base
[3] | The term "Base" here does not refer to a base class and is + |
[3] | The term "Base" here does not refer to a base class and is not meant to imply the use of derivation. We have followed the lead of the standard library, which provides a base() function to access the underlying iterator object of a reverse_iterator adaptor. |
The operations in this section are described in terms of operations on the core interface of Derived which may be inaccessible (i.e. private). The implementation should access these operations @@ -1146,7 +864,7 @@ through member functions of class
operator->() const; (see below)
+operator->() const; (see below)
static_cast<Derived*>(iterator_adaptor*) shall be well-formed. The Base argument shall be Assignable and Copy Constructible.
The V', C', R', and D' parameters of the iterator_facade used as a base class in the summary of iterator_adaptor above are defined as follows:
@@ -1592,8 +1310,8 @@ expression involving ``Derived`` in those concepts' requirements. -->iterator_adaptor();
Base const& base_reference() const;
typename iterator_adaptor::reference dereference() const;
The enable_if_convertible<X,Y>::type expression used in this section is for exposition purposes. The converting constructors for specialized adaptors should be only be in an overload set provided @@ -1745,8 +1463,8 @@ diagnostic required.
take the constructor out of the overload set when the types are not implicitly convertible. ] -The expression *v, where v is an object of iterator_traits<Iterator>::value_type, shall be valid expression and convertible to reference. Iterator shall @@ -1932,8 +1650,8 @@ the requirements indicated by ite parameter is not use_default, as implied by the algorithm for deducing the default for the value_type member.]
In addition to the concepts indicated by iterator_category and by iterator_traversal<indirect_iterator>::type, a specialization of indirect_iterator models the following @@ -1953,8 +1671,8 @@ expression (where t i indirect_iterator<Y,V2,C2,R2,D2> if and only if X is interoperable with Y.
In addition to the operations required by the concepts described above, specializations of indirect_iterator provide the following operations.
@@ -2045,15 +1763,15 @@ indirect_iterator(The reverse iterator adaptor iterates through the adapted iterator range in the opposite direction.
-Iterator must be a model of Bidirectional Traversal Iterator. The type iterator_traits<Iterator>::reference must be the type of *i, where i is an object of type Iterator.
A specialization of reverse_iterator models the same iterator traversal and iterator access concepts modeled by its Iterator argument. In addition, it may model old iterator concepts @@ -2137,8 +1855,8 @@ Random Access Traversal Iterator reverse_iterator<Y> if and only if X is interoperable with Y.
In addition to the operations required by the concepts modeled by reverse_iterator, reverse_iterator provides the following operations.
@@ -2228,16 +1946,16 @@ return *--tmp;The transform iterator adapts an iterator by modifying the operator* to apply a function object to the result of dereferencing the iterator and returning the result.
-The type UnaryFunction must be Assignable, Copy Constructible, and the expression f(*i) must be valid where f is an object of type UnaryFunction, i is an object of type Iterator, and @@ -2301,8 +2019,8 @@ where the type of f(*i)result_of<UnaryFunction(iterator_traits<Iterator>::reference)>::type.
The argument Iterator shall model Readable Iterator.
The resulting transform_iterator models the most refined of the following that is also modeled by Iterator.
@@ -2348,8 +2066,8 @@ mutable iterator (as defined in the old iterator requirements). transform_iterator<F2, Y, R2, V2> if and only if X is interoperable with Y.
In addition to the operations required by the concepts modeled by transform_iterator, transform_iterator provides the following operations.
@@ -2444,8 +2162,8 @@ initialized to t.functor()The Iterator argument shall meet the requirements of Readable Iterator and Single Pass Iterator or it shall meet the requirements of Input Iterator.
@@ -2515,8 +2233,8 @@ the expression p(x) m iterator_traits<Iterator>::value_type, and where the type of p(x) must be convertible to bool.The concepts that filter_iterator models are dependent on which concepts the Iterator argument models, as specified in the following tables.
@@ -2592,8 +2310,8 @@ following tables.filter_iterator<P1, X> is interoperable with filter_iterator<P2, Y> if and only if X is interoperable with Y.
In addition to those operations required by the concepts that filter_iterator models, filter_iterator provides the following operations.
@@ -2703,16 +2421,16 @@ or m_pred(*m_iter)counting_iterator adapts an object by adding an operator* that returns the current value of the object. All other iterator operations are forwarded to the adapted object.
-The Incrementable argument shall be Copy Constructible and Assignable.
If iterator_category is convertible to forward_iterator_tag or forward_traversal_tag, the following must be well-formed:
@@ -2791,8 +2509,8 @@ n = i - j; i < j;Specializations of counting_iterator model Readable Lvalue Iterator. In addition, they model the concepts corresponding to the iterator tags to which their iterator_category is convertible. @@ -2807,8 +2525,8 @@ concepts modeled by Incrementable counting_iterator<Y,C2,D2> if and only if X is interoperable with Y.
In addition to the operations required by the concepts modeled by counting_iterator, counting_iterator provides the following operations.
@@ -2883,8 +2601,8 @@ operations.#include <boost/function_output_iterator.hpp>@@ -2928,17 +2646,17 @@ private: };
UnaryFunction must be Assignable and Copy Constructible.
function_output_iterator is a model of the Writable and Incrementable Iterator concepts.
explicit function_output_iterator(const UnaryFunction& f = UnaryFunction());
Author: | David Abrahams, Jeremy Siek, Thomas Witt | |
---|---|---|
Contact: | -dave@boost-consulting.com, jsiek@osl.iu.edu, witt@ive.uni-hannover.de | dave@boost-consulting.com, jsiek@osl.iu.edu, witt@ive.uni-hannover.de |
Organization: | -Boost Consulting, Indiana University Open Systems -Lab, University of Hanover Institute for Transport + | Boost Consulting, Indiana University Open Systems +Lab, University of Hanover Institute for Transport Railway Operation and Construction |
Date: | -2004-11-01 | 2006-09-11 |
Copyright: | Copyright David Abrahams, Jeremy Siek, and Thomas Witt 2003. |
Table of Contents
The Iterator argument shall meet the requirements of Readable Iterator and Single Pass Iterator or it shall meet the requirements of Input Iterator.
@@ -403,8 +121,8 @@ the expression p(x) m iterator_traits<Iterator>::value_type, and where the type of p(x) must be convertible to bool.The concepts that filter_iterator models are dependent on which concepts the Iterator argument models, as specified in the following tables.
@@ -480,8 +198,8 @@ following tables.filter_iterator<P1, X> is interoperable with filter_iterator<P2, Y> if and only if X is interoperable with Y.
In addition to those operations required by the concepts that filter_iterator models, filter_iterator provides the following operations.
@@ -622,8 +340,8 @@ make_filter_iterator(Iterator x, Iterator end = Iterator());This example uses filter_iterator and then make_filter_iterator to output only the positive integers from an array of integers. Then make_filter_iterator is is used to output @@ -682,8 +400,14 @@ int main() 4 5 8 0 -1 4 5 8 -
The source code for this example can be found here.
+The source code for this example can be found here.
Table of Contents
#include <boost/function_output_iterator.hpp>@@ -374,17 +92,17 @@ private: };
UnaryFunction must be Assignable and Copy Constructible.
function_output_iterator is a model of the Writable and Incrementable Iterator concepts.
explicit function_output_iterator(const UnaryFunction& f = UnaryFunction());
Table of Contents
The iterator categories defined in C++98 are extremely limiting because they bind together two orthogonal concepts: traversal and element access. For example, because a random access iterator is @@ -361,17 +83,17 @@ it is impossible to capture the capabilities of vector<bool>::iterator using the C++98 categories. This is the infamous "vector<bool> is not a container, and its iterators aren't random access iterators", debacle about which Herb Sutter -wrote two papers for the standards comittee (n1185 and n1211), -and a Guru of the Week. New-style iterators go well beyond +wrote two papers for the standards comittee (n1185 and n1211), +and a Guru of the Week. New-style iterators go well beyond patching up vector<bool>, though: there are lots of other iterators already in use which can't be adequately represented by the existing concepts. For details about the new iterator concepts, see our
-Standard Proposal For New-Style Iterators (PDF)+Standard Proposal For New-Style Iterators (PDF)
Writing standard-conforming iterators is tricky, but the need comes up often. In order to ease the implementation of new iterators, the Boost.Iterator library provides the iterator_facade class template, @@ -387,54 +109,54 @@ behavior as possible.
The documentation for these two classes can be found at the following web pages:
Both iterator_facade and iterator_adaptor as well as many of the specialized
+ Both iterator_facade and iterator_adaptor as well as many of the specialized
adaptors mentioned below have been proposed for standardization,
and accepted into the first C++ technical report; see our
-Standard Proposal For Iterator Facade and Adaptor (PDF)
+Standard Proposal For Iterator Facade and Adaptor (PDF)
for more details.
The iterator library supplies a useful suite of standard-conforming -iterator templates based on the Boost iterator facade and adaptor.
+iterator templates based on the Boost iterator facade and adaptor.If you have been using the old Boost Iterator Adaptor library to implement iterators, you probably wrote a Policies class which captures the core operations of your iterator. In the new library design, you'll move those same core operations into the body of the iterator class itself. If you were writing a family of iterators, -you probably wrote a type generator to build the +you probably wrote a type generator to build the iterator_adaptor specialization you needed; in the new library design you don't need a type generator (though may want to keep it around as a compatibility aid for older code) because, due to the -use of the Curiously Recurring Template Pattern (CRTP) [Cop95], +use of the Curiously Recurring Template Pattern (CRTP) [Cop95], you can now define the iterator class yourself and acquire functionality through inheritance from iterator_facade or iterator_adaptor. As a result, you also get much finer control @@ -475,8 +197,8 @@ template argument, if explicitly specified) is a true reference type, transform_iterator will behave like projection_iterator used to.
In 2000 Dave Abrahams was writing an iterator for a container of pointers, which would access the pointed-to elements when dereferenced. Naturally, being a library writer, he decided to @@ -504,7 +226,7 @@ library you see today.
[Cop95] | [Coplien, 1995] Coplien, J., Curiously Recurring Template + |
[Cop95] | [Coplien, 1995] Coplien, J., Curiously Recurring Template Patterns, C++ Report, February 1995, pp. 24-27. |
Table of Contents
The expression *v, where v is an object of iterator_traits<Iterator>::value_type, shall be valid expression and convertible to reference. Iterator shall @@ -440,8 +158,8 @@ the requirements indicated by ite parameter is not use_default, as implied by the algorithm for deducing the default for the value_type member.]
In addition to the concepts indicated by iterator_category and by iterator_traversal<indirect_iterator>::type, a specialization of indirect_iterator models the following @@ -461,8 +179,8 @@ expression (where t i indirect_iterator<Y,V2,C2,R2,D2> if and only if X is interoperable with Y.
In addition to the operations required by the concepts described above, specializations of indirect_iterator provide the following operations.
@@ -555,8 +273,8 @@ indirect_iterator(This example prints an array of characters, using indirect_iterator to access the array of characters through an array of pointers. Next indirect_iterator is used with the @@ -614,8 +332,14 @@ a,b,c,d,e,f,g, b,c,d,e,f,g,h, a,b,c,d,e,f,g, -
The source code for this example can be found here.
+The source code for this example can be found here.
Author: | -David Abrahams and Jeremy Siek |
---|---|
Contact: | -dave@boost-consulting.com, jsiek@osl.iu.edu |
Organization: | -Boost Consulting, Indiana University Bloomington |
Date: | -2003-11-19 |
Copyright: | -Copyright David Abrahams, Jeremy Siek 2003. Use, modification and -distribution is subject to the Boost Software License, -Version 1.0. (See accompanying file LICENSE_1_0.txt or copy -at http://www.boost.org/LICENSE_1_0.txt) |
The is_writable and is_swappable traits classes in N1550 -provide a mechanism for determining at compile time if an iterator -type is a model of the new Writable Iterator and Swappable Iterator -concepts, analogous to iterator_traits<X>::iterator_category -for the old iterator concepts. For backward compatibility, -is_writable and is_swappable not only work with new -iterators, but they also are intended to work for old -iterators (iterators that meet the requirements for one of the -iterator concepts in the current standard). In the case of old -iterators, the writability and swapability is deduced based on the -iterator_category and also the reference type. The -specification for this deduction gives false positives for forward -iterators that have non-assignable value types.
-To review, the part of the is_writable trait definition which -applies to old iterators is:
--if (cat is convertible to output_iterator_tag) - return true; -else if (cat is convertible to forward_iterator_tag - and iterator_traits<Iterator>::reference is a - mutable reference) - return true; -else - return false; --
Suppose the value_type of the iterator It has a private -assignment operator:
--class B { -public: - ... -private: - B& operator=(const B&); -}; --
and suppose the reference type of the iterator is B&. In -that case, is_writable<It>::value will be true when in fact -attempting to write into B will cause an error.
-The same problem applies to is_swappable.
-Remove the is_writable and is_swappable traits, and remove the -requirements in the Writable Iterator and Swappable Iterator concepts -that require their models to support these traits.
-Change the is_readable specification to be: -is_readable<X>::type is true_type if the -result type of X::operator* is convertible to -iterator_traits<X>::value_type and is false_type -otherwise. Also, is_readable is required to satisfy -the requirements for the UnaryTypeTrait concept -(defined in the type traits proposal).
-Remove the requirement for support of the is_readable trait from -the Readable Iterator concept.
-Remove the iterator_tag class.
-Change the specification of traversal_category to:
--traversal-category(Iterator) = - let cat = iterator_traits<Iterator>::iterator_category - if (cat is convertible to incrementable_iterator_tag) - return cat; // Iterator is a new iterator - else if (cat is convertible to random_access_iterator_tag) - return random_access_traversal_tag; - else if (cat is convertible to bidirectional_iterator_tag) - return bidirectional_traversal_tag; - else if (cat is convertible to forward_iterator_tag) - return forward_traversal_tag; - else if (cat is convertible to input_iterator_tag) - return single_pass_iterator_tag; - else if (cat is convertible to output_iterator_tag) - return incrementable_iterator_tag; - else - return null_category_tag; --
Table of Contents
The iterator_adaptor class template adapts some Base [1] +
The iterator_adaptor class template adapts some Base1 type to create a new iterator. Instantiations of iterator_adaptor are derived from a corresponding instantiation of iterator_facade and implement the core behaviors in terms of the Base type. In @@ -373,7 +91,7 @@ instance of the Base
[1] | (1, 2) The term "Base" here does not refer to a base class and is + |
[1] | (1, 2) The term "Base" here does not refer to a base class and is not meant to imply the use of derivation. We have followed the lead of the standard library, which provides a base() function to access the underlying iterator object of a reverse_iterator adaptor. |
Base const& base_reference() const;
typename iterator_adaptor::reference dereference() const;
In this section we'll further refine the node_iter class -template we developed in the iterator_facade tutorial. If you haven't already +template we developed in the iterator_facade tutorial. If you haven't already read that material, you should go back now and check it out because we're going to pick up right where it left off.
+Table of Contents
namespace iterator_archetypes { @@ -373,8 +91,8 @@ class iterator_archetype };
The access category types provided correspond to the following standard iterator access concept combinations:
@@ -399,23 +117,23 @@ writeable_lvalue_iterator_t := Readable Iterator & Writeable Iterator & Swappable Iterator & Lvalue Iterator
The AccessCategory argument must be one of the predefined access category tags. The TraversalCategory must be one of the standard traversal tags. The Value type must satisfy the requirements of the iterator concept specified by AccessCategory and TraversalCategory as implied by the nested traits types.
iterator_archetype models the iterator concepts specified by the AccessCategory and TraversalCategory arguments. iterator_archetype does not model any other access concepts or any more derived traversal concepts.
For an introduction to using concept checking classes, see -the documentation for the boost::concept_check library.
-namespace boost_concepts { @@ -398,6 +116,12 @@ namespace boost_concepts {
Table of Contents
Iterator facade uses the Curiously Recurring Template -Pattern (CRTP) [Cop95] so that the user can specify the behavior +Pattern (CRTP) [Cop95] so that the user can specify the behavior of iterator_facade in a derived class. Former designs used policy objects to specify the behavior, but that approach was discarded for several reasons:
@@ -415,8 +133,8 @@ iterators, and a separate iterato impossible. -The user of iterator_facade derives his iterator class from a specialization of iterator_facade and passes the derived iterator class as iterator_facade's first template parameter. @@ -479,8 +197,8 @@ constructor. Finally, if the iterator is to model Forward Traversal Iterator or a more-refined iterator concept, a default constructor is required.
iterator_facade and the operator implementations need to be able to access the core member functions in the derived class. Making the core member functions public would expose an implementation detail to @@ -513,19 +231,19 @@ standardize the gateway protocol. Note that even if open a safety loophole, as every core member function preserves the invariants of the iterator.
The indexing operator for a generalized iterator presents special challenges. A random access iterator's operator[] is only required to return something convertible to its value_type. Requiring that it return an lvalue would rule out currently-legal random-access iterators which hold the referenced value in a data -member (e.g. counting_iterator), because *(p+n) is a reference +member (e.g. counting_iterator), because *(p+n) is a reference into the temporary iterator p+n, which is destroyed when operator[] returns.
Writable iterators built with iterator_facade implement the -semantics required by the preferred resolution to issue 299 and -adopted by proposal n1550: the result of p[n] is an object +semantics required by the preferred resolution to issue 299 and +adopted by proposal n1550: the result of p[n] is an object convertible to the iterator's value_type, and p[n] = x is equivalent to *(p + n) = x (Note: This result object may be implemented as a proxy containing a copy of p+n). This approach @@ -536,8 +254,8 @@ the implementation of her iterator is free to implement an class; it will hide the one supplied by iterator_facade from clients of her iterator.
The reference type of a readable iterator (and today's input
iterator) need not in fact be a reference, so long as it is
convertible to the iterator's value_type. When the value_type
@@ -552,14 +270,14 @@ satisfied by the iterator_facade<
[Cop95] (1, 2) [Coplien, 1995] Coplien, J., Curiously Recurring Template
+ [Cop95] (1, 2) [Coplien, 1995] Coplien, J., Curiously Recurring Template
Patterns, C++ Report, February 1995, pp. 24-27.
The following table describes the typical valid expressions on iterator_facade's Derived parameter, depending on the iterator concept(s) it will model. The operations in the first @@ -736,8 +454,8 @@ object of type X, X, and z is a constant object of a random access traversal iterator type interoperable with X.
-iterator_facade Core Operations
+iterator_facade Core Operations
The operations in this section are described in terms of operations on
the core interface of Derived which may be inaccessible
(i.e. private). The implementation should access these operations
@@ -811,7 +529,7 @@ through member functions of class
- operator->() const; (see below) operator->() const; (see below)
In this section we'll walk through the implementation of a few iterators using iterator_facade, based around the simple example of a linked list of polymorphic objects. This example was -inspired by a posting by Keith Macdonald on the Boost-Users +inspired by a posting by Keith Macdonald on the Boost-Users mailing list.
-Say we've written a polymorphic linked list node base class:
# include <iostream> @@ -1212,8 +930,8 @@ inline std::ostream& operator<<(std::ostream& s, node_base const&aOur first challenge is to build an appropriate iterator over these lists.
We will construct a node_iterator class using inheritance from iterator_facade to implement most of the iterator's operations.
@@ -1226,45 +944,45 @@ class node_iterator ... };-
iterator_facade has several template parameters, so we must decide what types to use for the arguments. The parameters are Derived, Value, CategoryOrTraversal, Reference, and Difference.
-Because iterator_facade is meant to be used with the CRTP -[Cop95] the first parameter is the iterator class name itself, +[Cop95] the first parameter is the iterator class name itself, node_iterator.
The Value parameter determines the node_iterator's value_type. In this case, we are iterating over node_base objects, so Value will be node_base.
Now we have to determine which iterator traversal concept our +
Now we have to determine which iterator traversal concept our node_iterator is going to model. Singly-linked lists only have -forward links, so our iterator can't can't be a bidirectional +forward links, so our iterator can't can't be a bidirectional traversal iterator. Our iterator should be able to make multiple passes over the same linked list (unlike, say, an istream_iterator which consumes the stream it traverses), so it -must be a forward traversal iterator. Therefore, we'll pass -boost::forward_traversal_tag in this position [1].
+must be a forward traversal iterator. Therefore, we'll pass +boost::forward_traversal_tag in this position1.[1] | iterator_facade also supports old-style category + |
[1] | iterator_facade also supports old-style category tags, so we could have passed std::forward_iterator_tag here; either way, the resulting iterator's iterator_category will end up being std::forward_iterator_tag. |
The Reference argument becomes the type returned by node_iterator's dereference operation, and will also be the same as std::iterator_traits<node_iterator>::reference. The @@ -1272,8 +990,8 @@ library's default for this parameter is node_base& is a good choice for the iterator's reference type, we can omit this argument, or pass use_default.
The Difference argument determines how the distance between two node_iterators will be measured and will also be the same as std::iterator_traits<node_iterator>::difference_type. @@ -1299,15 +1017,15 @@ class node_iterator
Next we need to decide how to represent the iterator's position. This representation will take the form of data members, so we'll also need to write constructors to initialize them. The node_iterator's position is quite naturally represented using a pointer to a node_base. We'll need a constructor to build an iterator from a node_base*, and a default constructor to -satisfy the forward traversal iterator requirements [2]. +satisfy the forward traversal iterator requirements2. Our node_iterator then becomes:
# include "node.hpp" @@ -1337,20 +1055,20 @@ class node_iterator
[2] | Technically, the C++ standard places almost no + |
[2] | Technically, the C++ standard places almost no requirements on a default-constructed iterator, so if we were really concerned with efficiency, we could've written the default constructor to leave m_node uninitialized. |
The last step is to implement the core operations required by +
The last step is to implement the core operations required by the concepts we want our iterator to model. Referring to the -table, we can see that the first three rows are applicable +table, we can see that the first three rows are applicable because node_iterator needs to satisfy the requirements for -readable iterator, single pass iterator, and incrementable +readable iterator, single pass iterator, and incrementable iterator.
We therefore need to supply dereference, equal, and increment members. We don't want these members @@ -1392,11 +1110,11 @@ class node_iterator };
Voilà ; a complete and conforming readable, forward-traversal -iterator! For a working example of its use, see this program.
+iterator! For a working example of its use, see this program.Our const_node_iterator works perfectly well on its own, but taken together with node_iterator it doesn't quite meet expectations. For example, we'd like to be able to pass a @@ -1507,9 +1225,9 @@ just as you can with std::list< node_const_iterator into the same list, we should be able to compare them for equality.
This expected ability to use two different iterator types together -is known as interoperability. Achieving interoperability in +is known as interoperability. Achieving interoperability in our case is as simple as templatizing the equal function and -adding a templatized converting constructor [3] [4]:
+adding a templatized converting constructor34:template <class Value> class node_iter @@ -1554,23 +1272,23 @@ typedef impl::node_iterator<node_base const> node_const_iterator;
[3] | If you're using an older compiler and it can't handle -this example, see the example code for workarounds. |
[3] | If you're using an older compiler and it can't handle +this example, see the example code for workarounds. |
[4] | If node_iterator had been a random access
+[4] | If node_iterator had been a random access
traversal iterator, we'd have had to templatize its
distance_to function as well. | |
You can see an example program which exercises our interoperable -iterators here.
+iterators here.Now node_iterator and node_const_iterator behave exactly as you'd expect... almost. We can compare them and we can convert in one direction: from node_iterator to node_const_iterator. @@ -1579,15 +1297,15 @@ If we try to convert from node_co constructor tries to initialize node_iterator's m_node, a node* with a node const*. So what's the problem?
The problem is that -boost::is_convertible<node_const_iterator,node_iterator>::value -will be true, but it should be false. is_convertible +boost::is_convertible<node_const_iterator,node_iterator>::value +will be true, but it should be false. is_convertible lies because it can only see as far as the declaration of node_iter's converting constructor, but can't look inside at the definition to make sure it will compile. A perfect solution would make node_iter's converting constructor disappear when the m_node conversion would fail.
In fact, that sort of magic is possible using -boost::enable_if. By rewriting the converting constructor as +boost::enable_if. By rewriting the converting constructor as follows, we can remove it from the overload set when it's not appropriate:
@@ -1611,14 +1329,20 @@ public: : m_node(other.m_node) {}
This concludes our iterator_facade tutorial, but before you -stop reading we urge you to take a look at iterator_adaptor. +stop reading we urge you to take a look at iterator_adaptor. There's another way to approach writing these iterators which might even be superior.
std::iterator_traits provides access to five associated types of any iterator: its value_type, reference, pointer, iterator_category, and difference_type. Unfortunately, such a "multi-valued" traits template can be difficult to use in a metaprogramming context. <boost/iterator/iterator_traits.hpp> -provides access to these types using a standard metafunctions.
+provides access to these types using a standard metafunctions.Header <boost/iterator/iterator_traits.hpp>:
template <class Iterator> @@ -380,14 +98,14 @@ struct iterator_category };
Because of workarounds in Boost, you may find that these -metafunctions actually work better than the facilities provided by +metafunctions actually work better than the facilities provided by your compiler's standard library.
On compilers that don't support partial specialization, such as Microsoft Visual C++ 6.0 or 7.0, you may need to manually invoke -BOOST_BROKEN_COMPILER_TYPE_TRAITS_SPECIALIZATION on the +BOOST_BROKEN_COMPILER_TYPE_TRAITS_SPECIALIZATION on the value_type of pointers that are passed to these metafunctions.
Because of bugs in the implementation of GCC-2.9x, the name of iterator_category is changed to iterator_category_ on that @@ -395,6 +113,12 @@ compiler. A macro, BOOST_ITERATO either iterator_category or iterator_category_, as appropriate to the platform, is provided for portability.
Table of Contents
The standard iterator categories and requirements are flawed because they use a single hierarchy of concepts to address two orthogonal issues: iterator traversal and value access. As a result, many @@ -409,12 +127,12 @@ requirements in the iterator categories.
This proposal for TR1 is a pure extension. Further, the new iterator concepts are backward-compatible with the old iterator requirements, and old iterators are forward-compatible with the new iterator @@ -474,13 +192,13 @@ made it). -DWA --> standards conforming input iterator is allowed to have a tag that is not input_iterator_tag but that is convertible to input_iterator_tag? -JGS --> -
The extensions in this paper suggest several changes we might make to the working paper for the next standard. These changes are not a formal part of this proposal for TR1.
-The algorithms in the standard library could benefit from the new iterator concepts because the new concepts provide a more accurate way to express their type requirements. The result is algorithms that are @@ -544,15 +262,15 @@ Bidirectional Iterator (2) -> Bidirectional Traversal Iterator and Writable I
For the next working paper (but not for TR1), the committee should consider deprecating the old iterator tags, and std::iterator_traits, since it will be superceded by individual traits metafunctions.
For the next working paper (but not for TR1), the committee should consider reclassifying vector<bool>::iterator as a Random Access Traversal Iterator and Readable Iterator and Writable @@ -560,8 +278,8 @@ Iterator.
The iterator requirements are to be separated into two groups. One set of concepts handles the syntax and semantics of value access:
In the tables below, X is an iterator type, a is a constant object of type X, R is std::iterator_traits<X>::reference, T is std::iterator_traits<X>::value_type, and v is a constant object of type T.
-A class or built-in type X models the Readable Iterator concept for value type T if, in addition to X being Assignable and Copy Constructible, the following expressions are valid and respect @@ -685,8 +403,8 @@ non-cv-qualified type
A class or built-in type X models the Writable Iterator concept if, in addition to X being Copy Constructible, the following expressions are valid and respect the stated semantics. Writable @@ -715,8 +433,8 @@ value types of X
A class or built-in type X models the Swappable Iterator concept if, in addition to X being Copy Constructible, the following expressions are valid and respect the stated semantics.
@@ -742,12 +460,12 @@ exchanged -[Note: An iterator that is a model of the Readable Iterator and
-Writable Iterator concepts is also a model of Swappable
+ [Note: An iterator that is a model of the Readable Iterator and
+Writable Iterator concepts is also a model of Swappable
Iterator. --end note]
The Lvalue Iterator concept adds the requirement that the return type of operator* type be a reference to the value type of the iterator.
@@ -776,20 +494,20 @@ dereferenceable. -If X is a Writable Iterator then a == b if and only if
-*a is the same object as *b. If X is a Readable
+ If X is a Writable Iterator then a == b if and only if
+*a is the same object as *b. If X is a Readable
Iterator then a == b implies *a is the same object as
*b.
In the tables below, X is an iterator type, a and b are constant objects of type X, r and s are mutable objects of type X, T is std::iterator_traits<X>::value_type, and v is a constant object of type T.
-A class or built-in type X models the Incrementable Iterator concept if, in addition to X being Assignable and Copy Constructible, the following expressions are valid and respect the @@ -828,16 +546,16 @@ stated semantics.
-If X is a Writable Iterator then X a(r++); is equivalent +
If X is a Writable Iterator then X a(r++); is equivalent to X a(r); ++r; and *r++ = o is equivalent to *r = o; ++r. -If X is a Readable Iterator then T z(*r++); is equivalent +If X is a Readable Iterator then T z(*r++); is equivalent to T z(*r); ++r;.
A class or built-in type X models the Single Pass Iterator concept if the following expressions are valid and respect the stated semantics.
@@ -849,7 +567,8 @@ semantics.A class or built-in type X models the Forward Traversal Iterator concept if, in addition to X meeting the requirements of Default Constructible and Single Pass Iterator, the following expressions are @@ -939,8 +658,8 @@ dereferenceable implies
A class or built-in type X models the Bidirectional Traversal
Iterator concept if, in addition to X meeting the requirements of
Forward Traversal Iterator, the following expressions are valid and
@@ -1002,8 +721,8 @@ implies r
- A class or built-in type X models the Random Access Traversal
Iterator concept if the following expressions are valid and respect
the stated semantics. In the table below, Distance is
@@ -1074,13 +793,13 @@ value n of
A class or built-in type X that models Single Pass Iterator is
interoperable with a class or built-in type Y that also models
Single Pass Iterator if the following expressions are valid and
@@ -1240,8 +959,8 @@ the following additional requirements must be met. The is_readable_iterator class
-template satisfies the UnaryTypeTrait requirements. Given an iterator type X, is_readable_iterator<X>::value
yields true if, for an object a of type X, *a is
convertible to iterator_traits<X>::value_type, and false
@@ -1286,9 +1005,9 @@ otherwise.Random Access Traversal Iterators [lib.random.access.traversal.iterators]
+Random Access Traversal Iterators [lib.random.access.traversal.iterators]
a[n]
convertible to T
*(a + n)
-pre: a is a Readable
+ pre: a is a Readable
Iterator
a[n] = v
convertible to T
*(a + n) = v
-pre: a is a Writable
+ pre: a is a Writable
Iterator
a < b
@@ -1116,8 +835,8 @@ ordering relation
-Interoperable Iterators [lib.interoperable.iterators]
+Interoperable Iterators [lib.interoperable.iterators]
Addition to [lib.iterator.synopsis]
+Addition to [lib.iterator.synopsis]
// lib.iterator.traits, traits and tags
template <class Iterator> struct is_readable_iterator;
@@ -1254,10 +973,10 @@ struct bidirectional_traversal_tag : forward_traversal_tag { };
struct random_access_traversal_tag : bidirectional_traversal_tag { };
Addition to [lib.iterator.traits]
+Addition to [lib.iterator.traits]
Author:
Toon Knapen, David Abrahams, Roland Richter, Jeremy Siek
+Contact:
-dave@boost-consulting.com, jsiek@osl.iu.edu dave@boost-consulting.com, jsiek@osl.iu.edu Organization:
-Boost Consulting, Indiana University Open Systems
+ Boost Consulting, Indiana University Open Systems
Lab
+Date:
-2004-11-01 2006-09-11
Table of Contents
ElementIterator shall model Random Access Traversal Iterator. IndexIterator shall model Readable Iterator. The value type of the IndexIterator must be convertible to the difference type of ElementIterator.
permutation_iterator models the same iterator traversal concepts as IndexIterator and the same iterator access concepts as ElementIterator.
@@ -430,8 +148,8 @@ with permutation_iterator<E2,< X is interoperable with Y and E1 is convertible to E2.In addition to those operations required by the concepts that permutation_iterator models, permutation_iterator provides the following operations.
@@ -514,8 +232,8 @@ make_permutation_iterator(ElementIterator e, IndexIterator i);Have you ever wanted to write a generic function that can operate on any kind of dereferenceable object? If you have, you've probably run into the problem of how to determine the type that the @@ -338,8 +56,8 @@ void f(Dereferenceable p) ... } -
It turns out to be impossible to come up with a fully-general algorithm to do determine what-goes-here directly, but it is possible to require that pointee<Dereferenceable>::type is @@ -360,8 +78,8 @@ namespace boost }
indirect_reference<T>::type is rather more specialized than pointee, and is meant to be used to forward the result of dereferencing an object of its argument type. Most dereferenceable @@ -369,13 +87,13 @@ types just return a reference to their pointee, but some return proxy references or return the pointee by value. When that information is needed, call on indirect_reference.
Both of these templates are essential to the correct functioning of -indirect_iterator.
+indirect_iterator.Table of Contents
Iterator must be a model of Bidirectional Traversal Iterator. The type iterator_traits<Iterator>::reference must be the type of *i, where i is an object of type Iterator.
A specialization of reverse_iterator models the same iterator traversal and iterator access concepts modeled by its Iterator argument. In addition, it may model old iterator concepts @@ -424,8 +142,8 @@ Random Access Traversal Iterator reverse_iterator<Y> if and only if X is interoperable with Y.
In addition to the operations required by the concepts modeled by reverse_iterator, reverse_iterator provides the following operations.
@@ -534,8 +252,8 @@ with a current constrThe following example prints an array of characters in reverse order using reverse_iterator.
@@ -566,8 +284,14 @@ original sequence of letters: hello world! sequence in reverse order: !dlrow olleh sequence in double-reversed (normal) order: hello world!-
The source code for this example can be found here.
+The source code for this example can be found here.
Table of Contents
The type UnaryFunction must be Assignable, Copy Constructible, and the expression f(*i) must be valid where f is an object of type UnaryFunction, i is an object of type Iterator, and @@ -405,8 +123,8 @@ where the type of f(*i)result_of<UnaryFunction(iterator_traits<Iterator>::reference)>::type.
The argument Iterator shall model Readable Iterator.
The resulting transform_iterator models the most refined of the following that is also modeled by Iterator.
@@ -452,8 +170,8 @@ mutable iterator (as defined in the old iterator requirements). transform_iterator<F2, Y, R2, V2> if and only if X is interoperable with Y.
In addition to the operations required by the concepts modeled by transform_iterator, transform_iterator provides the following operations.
@@ -581,8 +299,8 @@ default constructed and m_iteratoThis is a simple example of using the transform_iterators class to generate iterators that multiply (or add to) the value returned by dereferencing the iterator. It would be cooler to use lambda library @@ -615,8 +333,14 @@ multiplying the array by 2: adding 4 to each element in the array: 5 6 7 8 9 10 11 12 -
The source code for this example can be found here.
+The source code for this example can be found here.
Table of Contents
All iterator types in the argument IteratorTuple shall model Readable Iterator.
The resulting zip_iterator models Readable Iterator.
The fact that the zip_iterator models only Readable Iterator does not prevent you from modifying the values that the individual iterators point @@ -418,8 +136,8 @@ models the least refined standard traversal concept in this set.
zip_iterator<IteratorTuple2> if and only if IteratorTuple1 is interoperable with IteratorTuple2.In addition to the operations required by the concepts modeled by zip_iterator, zip_iterator provides the following operations.
@@ -538,8 +256,8 @@ initialized to t.