diff --git a/iterator_adaptors.htm b/iterator_adaptors.htm index d7f9019..62cf274 100644 --- a/iterator_adaptors.htm +++ b/iterator_adaptors.htm @@ -52,14 +52,6 @@ Counting Iterator Adaptor - -
Dave Abrahams started the library, applying policies class technique @@ -109,16 +101,16 @@ struct iterator_adaptor; typedef Reference reference; typedef Category iterator_category; typedef Base base_type; + typedef Policies policies_type; iterator_adaptor(); iterator_adaptor(const Base&, const Policies& = Policies()); base_type base() const; - template <class Iter2, class Value2, class Pointer2, class Reference2> + template <class B, class V, class R, class P> iterator_adaptor ( - const iterator_adaptor<Iter2,Policies,Value2,Reference2,Pointer2,Category,Distance>& - : m_iter_p(src.iter(), src.policies()); + const iterator_adaptor<B,Policies,V,R,P,Category,Distance>&); reference operator*() const; operator_arrow_result_type operator->() const; [2] @@ -135,50 +127,27 @@ struct iterator_adaptor; iterator_adaptor& operator-(Distance x) const; }; -template <class B, class Policies, class V, class R, class P, +template <class B, class P, class V, class R, class Ptr, class C, class D1, class D2> -iterator_adaptor<B,Policies,V,R,P,C,D1> -operator+(iterator_adaptor<B,P,V,R,P,C,D1>, D2); +iterator_adaptor<B,P,V,R,Ptr,C,D1> +operator+(iterator_adaptor<B,P,V,R,Ptr,C,D1>, D2); -template <class B, class Policies, class V, class R, class P, +template <class B, class P, class V, class R, class Ptr, class C, class D1, class D2> -iterator_adaptor<B,Policies,V,R,P,C,D1> -operator+(D2, iterator_adaptor<B,P,V,R,P,C,D1> p); +iterator_adaptor<B,P,V,R,P,C,D1> +operator+(D2, iterator_adaptor<B,P,V,R,Ptr,C,D1> p); -template <class B1, class B2, class Policies, class V1, class V2, +template <class B1, class B2, class P, class V1, class V2, class R1, class R2, class P1, class P2, class C, class D> Distance operator-(const iterator_adaptor<B1,P,V1,R1,P1,C,D>&, const iterator_adaptor<B2,P,V2,R2,P2,C,D>&); -template <class B1, class B2, class Policies, class V1, class V2, +template <class B1, class B2, class P, class V1, class V2, class R1, class R2, class P1, class P2, class C, class D> bool operator==(const iterator_adaptor<B1,P,V1,R1,P1,C,D>&, const iterator_adaptor<B2,P,V2,R2,P2,C,D>&); -template <class B1, class B2, class Policies, class V1, class V2, - class R1, class R2, class P1, class P2, class C, class D> -bool operator!=(const iterator_adaptor<B1,P,V1,R1,P1,C,D>&, - const iterator_adaptor<B2,P,V2,R2,P2,C,D>&); - -template <class B1, class B2, class Policies, class V1, class V2, - class R1, class R2, class P1, class P2, class C, class D> -bool operator<(const iterator_adaptor<B1,P,V1,R1,P1,C,D>&, - const iterator_adaptor<B2,P,V2,R2,P2,C,D>&); - -template <class B1, class B2, class Policies, class V1, class V2, - class R1, class R2, class P1, class P2, class C, class D> -bool operator<=(const iterator_adaptor<B1,P,V1,R1,P1,C,D>&, - const iterator_adaptor<B2,P,V2,R2,P2,C,D>&); - -template <class B1, class B2, class Policies, class V1, class V2, - class R1, class R2, class P1, class P2, class C, class D> -bool operator>=(const iterator_adaptor<B1,P,V1,R1,P1,C,D>&, - const iterator_adaptor<B2,P,V2,R2,P2,C,D>&); - -template <class B1, class B2, class Policies, class V1, class V2, - class R1, class R2, class P1, class P2, class C, class D> -bool operator>(const iterator_adaptor<B1,P,V1,R1,P1,C,D>&, - const iterator_adaptor<B2,P,V2,R2,P2,C,D>&); +// and similarly for operators !=, <, <=, >=, >
@@ -276,7 +245,6 @@ struct default_iterator_policies - To implement a transform iterator we will only change one of the base iterator's behaviors, so the transform_iterator_policies class will inherit the rest @@ -287,8 +255,9 @@ struct default_iterator_policies value type of the base iterator) and we will need to know the result_type of the function, so - AdaptableUnaryFunction is the correct concept (set of - requirements) to choose for the function object type. Inside of + AdaptableUnaryFunction is the correct + + concept to choose for the function object type. Inside of transform_iterator_policies we will implement the dereference() member function. This member function will dereference the base iterator (the second parameter of @@ -321,13 +290,11 @@ struct default_iterator_policies construct the transform iterator type. The nicest way to package up the construction of the transform iterator is to create a type - generator, which is a class whose sole purpose is to - create a typedef for some new type based on several template - parameters. The first template parameter will be the type of the - function object and the second will be the base iterator - type. Inside the transform_iterators class we use the - iterator_adaptor class to create the transform iterator - type. + generator. The first template parameter of the generator will + be the type of the function object and the second will be the base + iterator type. Inside the transform_iterator_generator + class we use the iterator_adaptor class to create the + transform iterator type.
@@ -405,18 +372,9 @@ This output is:Description - Predicate + Base - The function object that determines which elements are retained and - which elements are skipped. - - - BaseIterator - - The iterator type being wrapped. This type must at least be a model - of the InputIterator concept. + The type being wrapped. Value @@ -451,10 +409,7 @@ This output is: Category The iterator_category type for the resulting iterator. - Typically the default for this parameter is the appropriate type. If - you override this parameter, do not use - bidirectional_iterator_tag because filter iterators can not go - in reverse.
+ Typically the default for this parameter is the appropriate type.
Default: std::iterator_traits<BaseIterator>::iterator_category @@ -467,7 +422,66 @@ This output is: std::iterator_traits<BaseIterator>::difference_type + +Model of
+ + Depending on the Base and Policies template + parameters, an iterator_adaptor can be a Input + Iterator, Forward + Iterator, + Bidirectional Iterator, or + Random Access Iterator. + +Members
+ + In addition to all of the member functions required of a + Random Access Iterator, the iterator_adaptor class + template defines the following members. + ++
+
++ + +iterator_adaptor(const Base&, const Policies& = Policies()) +
+Construct an iterator adaptor from a base object and a policies object. ++ + +template <class B, class V, class R, class P>
+iterator_adaptor(const iterator_adaptor<B,Policies,V,R,P,Category,Distance>&) +
+This constructor allows for conversion from mutable to constant iterator +adaptors. This assumes that the type B is convertible to the +type Base. ++ + +base_type base() const; +
+Return a copy of the base object. +Operators
+ + The iterator_adaptor class defines all of the operators + required of a + + Random Access Iterator. Also, the operators of the + iterator_adaptor class that take two iterator adaptor + arguments (difference and comparisons) are defined in such a way + that the operators work on pairs of iterator_adaptor + types that have different template parameters, provided that the + base types of the iterator adaptors are interoperable. The reason + for this is so that mutable and constant versions of an iterator + adaptor can be created that will be interoperable with eachother. +Challenge
There is an unlimited number of ways the the @@ -490,6 +504,20 @@ This output is: in a stardard conforming fashion, providing access to members of the objects pointed to by the iterator. +
Implemenation Notes
+ ++
+- The iterator_adaptor::operator[] returns by-value + instead of by-reference as might be expected. There are two + reasons for this. First, the C++ standard only requires that + the return type by ``convertible to T'' (Table 76). Second, + and more importantly, for certain kinds of iterators, + returning a reference could cause serious memory problems due + to the reference being bound to a temporary object whose + lifetime ends inside of the operator[].
+ +
Revised