Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống
1
/ 197 trang
THÔNG TIN TÀI LIỆU
Thông tin cơ bản
Định dạng
Số trang
197
Dung lượng
714,39 KB
Nội dung
24.1.1 Input iterators DRAFT: 28 April 1995 Iterators library 24–3 2 [Note: For input iterators, a == b does not imply ++a == ++b. (Equality does not guarantee the substi- tution property or referential transparency.) Algorithms on input iterators should never attempt to pass through the same iterator twice. They should be single pass algorithms. Value type T is not required to be an lvalue type. These algorithms can be used with istreams as the source of the input data through the istream_iterator class. —end note] [lib.output.iterators] 24.1.2 Output iterators 1 A class or a built-in type X satisfies the requirements of an output iterator if the following expressions are valid, as shown in Table 58: Table 58—Output iterator requirements _ _________________________________________________________________________ operational assertion/note expression return type semantics pre/post-condition _ _________________________________________________________________________ _ _________________________________________________________________________ X(a) a = t is equivalent to X(a) = t. note: a destructor is assumed. _ _________________________________________________________________________ X u(a); X u = a; _ _________________________________________________________________________ *a = t result is not used _ _________________________________________________________________________ ++r X& &r == &++r. _ _________________________________________________________________________ r++ convertible to const X& { X tmp = r; ++r; return tmp; } _ _________________________________________________________________________ *r++ = t result is not used _ _________________________________________________________________________ 2 [Note: The only valid use of an operator* is on the left side of the assignment statement. Assignment through the same value of the iterator happens only once. Algorithms on output iterators should never attempt to pass through the same iterator twice. They should be single pass algorithms. Equality and inequality might not be defined. Algorithms that take output iterators can be used with ostreams as the des- tination for placing data through the ostream_iterator class as well as with insert iterators and insert pointers. —end note] [lib.forward.iterators] 24.1.3 Forward iterators 1 A class or a built-in type X satisfies the requirements of a forward iterator if the following expressions are valid, as shown in Table 59: 24–4 Iterators library DRAFT: 28 April 1995 24.1.3 Forward iterators Table 59—Forward iterator requirements _ _______________________________________________________________________________ operational assertion/note expression return type semantics pre/post-condition _ _______________________________________________________________________________ _ _______________________________________________________________________________ X u; note: u might have a singular value. note: a destructor is assumed. _ _______________________________________________________________________________ X() note: X() might be singular. _ _______________________________________________________________________________ X(a) a == X(a). _ _______________________________________________________________________________ X u(a); X u; u = a; post: u == a. X u = a; _ _______________________________________________________________________________ a == b convertible to bool == is an equivalence relation. _ _______________________________________________________________________________ a != b convertible to bool !(a == b) _ _______________________________________________________________________________ r = a X& post: r == a. _ _______________________________________________________________________________ *a T& pre: a is dereferenceable. a == b implies *a == *b. If X is mutable, *a = t is valid. _ _______________________________________________________________________________ ++r X& pre: r is dereferenceable. post: r is dereferenceable or r is past-the-end. r == s and r is dereference- able implies ++r == ++s. &r == &++r. _ _______________________________________________________________________________ r++ convertible to const X& { X tmp = r; ++r; return tmp; } _ _______________________________________________________________________________ *r++ T& _ _______________________________________________________________________________ 2 [Note: The condition that a == b implies ++a == ++b (which is not true for input and output iterators) and the removal of the restrictions on the number of the assignments through the iterator (which applies to output iterators) allows the use of multi-pass one-directional algorithms with forward iterators. —end note] [lib.bidirectional.iterators] 24.1.4 Bidirectional iterators 1 A class or a built-in type X satisfies the requirements of a bidirectional iterator if, in addition to satisfying the requirements for forward iterators, the following expressions are valid as shown in Table 60: 24.1.4 Bidirectional iterators DRAFT: 28 April 1995 Iterators library 24–5 Table 60—Bidirectional iterator requirements (in addition to forward iterator) ______________________________________________________________________ operational assertion/note expression return type semantics pre/post-condition ______________________________________________________________________ ______________________________________________________________________ r X& pre: there exists s such that r == ++s. post: s is dereferenceable. (++r) == r. r == r implies r == s. &r == & r. ______________________________________________________________________ r convertible to const X& { X tmp = r; r; return tmp; } ______________________________________________________________________ *r convertible to T ______________________________________________________________________ 2 [Note: Bidirectional iterators allow algorithms to move iterators backward as well as forward. —end note] [lib.random.access.iterators] 24.1.5 Random access iterators 1 A class or a built-in type X satisfies the requirements of a random access iterator if, in addition to satisfying the requirements for bidirectional iterators, the following expressions are valid as shown in Table 61: 24–6 Iterators library DRAFT: 28 April 1995 24.1.5 Random access iterators Table 61—Random access iterator requirements (in addition to bidirectional iterator) _ __________________________________________________________________________ operational assertion/note expression return type semantics pre/post-condition _ __________________________________________________________________________ _ __________________________________________________________________________ r += n X& { Distance m = n; if (m >= 0) while (m ) ++r; else while (m++) r; return r; } _ __________________________________________________________________________ a + n { X tmp = a; return tmp += n; } n + a X a + n == n + a. _ __________________________________________________________________________ r -= n X& return r += -n; _ __________________________________________________________________________ a - n X { X tmp = a; return tmp -= n; } _ __________________________________________________________________________ b - a Distance { TBS } pre: there exists a value n of Distance such that a + n == b. b == a + (b - a). _ __________________________________________________________________________ a[n] convertible to T *(a + n) _ __________________________________________________________________________ a < b convertible to bool b - a > 0 < is a total ordering relation _ __________________________________________________________________________ a > b convertible to bool b < a > is a total ordering relation opposite to <. _ __________________________________________________________________________ a >= b convertible to bool !(a < b) _ __________________________________________________________________________ a <= b convertible to bool !(a > b) _ __________________________________________________________________________ [lib.iterator.tags] 24.1.6 Iterator tags 1 To implement algorithms only in terms of iterators, it is often necessary to infer both of the value type and the distance type from the iterator. To enable this task it is required that for an iterator i of any category other than output iterator, the expression value_type(i) returns (T*)(0) and the expression distance_type(i) returns (Distance*)(0). For output iterators, these expressions are not required. 2 [Note: For all the regular pointer types, value_type() and distance_type() can be defined with the help of: template <class T> inline T* value_type(const T*) { return (T*)(0); } template <class T> inline ptrdiff_t* distance_type(const T*) { return (ptrdiff_t*)(0); } —end note] 3 [Example: To implement a generic reverse function, a C + + program can do the following: 24.1.6 Iterator tags DRAFT: 28 April 1995 Iterators library 24–7 template <class BidirectionalIterator> inline void reverse(BidirectionalIterator first, BidirectionalIterator last) { __reverse(first, last, value_type(first), distance_type(first)); } 4 where __reverse is defined as: template <class BidirectionalIterator, class T, class Distance> void __reverse(BidirectionalIterator first, BidirectionalIterator last, T*, Distance*) { Distance n; distance(first, last, n); // see Iterator operations section n; while (n > 0) { T tmp = *first; *first++ = * last; *last = tmp; n -= 2; } } —end example] 5 [Note: If there is an additional pointer type far such that the difference of two far pointers is of the type long, an implementation may define: template <class T> inline T* value_type(const T far *) { return (T*)(0); } template <class T> inline long* distance_type(const T far *) { return (long*)(0); } —end note] 6 It is often desirable for a template function to find out what is the most specific category of its iterator argu- ment, so that the function can select the most efficient algorithm at compile time. To facilitate this, the library introduces category tag classes which are used as compile time tags for algorithm selection. They are: input_iterator_tag, output_iterator_tag, forward_iterator_tag, bidirectional_iterator_tag and random_access_iterator_tag. Every iterator i must have an expression iterator_category(i) defined on it that returns the most specific category tag that describes its behavior. 7 [Example: If the pointer types are defined to be in the random access iterator category by: template <class T> inline random_access_iterator_tag iterator_category(const T*) { return random_access_iterator_tag(); } 8 For a program-defined iterator BinaryTreeIterator, it can be included into the bidirectional iterator category by saying: template <class T> inline bidirectional_iterator_tag iterator_category( const BinaryTreeIterator<T>&) { return bidirectional_iterator_tag(); } —end example] 9 [Example: If a template function evolve() is well defined for bidirectional iterators, but can be imple- mented more efficiently for random access iterators, then the implementation is like: 24–8 Iterators library DRAFT: 28 April 1995 24.1.6 Iterator tags template <class BidirectionalIterator> inline void evolve(BidirectionalIterator first, BidirectionalIterator last) { evolve(first, last, iterator_category(first)); } template <class BidirectionalIterator> void evolve(BidirectionalIterator first, BidirectionalIterator last, bidirectional_iterator_tag) { // more generic, but less efficient algorithm } template <class RandomAccessIterator> void evolve(RandomAccessIterator first, RandomAccessIterator last, random_access_iterator_tag) { // more efficient, but less generic algorithm } —end example] 10 [Example: If a C + + program wants to define a bidirectional iterator for some data structure containing double and such that it works on a large memory model of the implementation, it can do so with: class MyIterator : public bidirectional_iterator<double, long> { // code implementing ++, etc. }; 11 Then there is no need to define iterator_category, value_type, and distance_type on MyIterator. —end example] Header <iterator> synopsis #include <cstddef> // for ptrdiff_t #include <iosfwd> // for istream, ostream #include <ios> // for ios_traits #include <streambuf> // for streambuf namespace std { // subclause _lib.library.primitives_, primitives: struct input_iterator_tag {}; struct output_iterator_tag {}; struct forward_iterator_tag {}; struct bidirectional_iterator_tag {}; struct random_access_iterator_tag {}; template <class T, class Distance = ptrdiff_t> struct input_iterator {}; struct output_iterator {}; template <class T, class Distance = ptrdiff_t> struct forward_iterator {}; template <class T, class Distance = ptrdiff_t> struct bidirectional_iterator {}; template <class T, class Distance = ptrdiff_t> struct random_access_iterator {}; 24.1.6 Iterator tags DRAFT: 28 April 1995 Iterators library 24–9 template <class T, class Distance> input_iterator_tag iterator_category(const input_iterator<T,Distance>&); output_iterator_tag iterator_category(const output_iterator&); template <class T, class Distance> forward_iterator_tag iterator_category(const forward_iterator<T,Distance>&); template <class T, class Distance> bidirectional_iterator_tag iterator_category(const bidirectional_iterator<T,Distance>&); template <class T, class Distance> random_access_iterator_tag iterator_category(const random_access_iterator<T,Distance>&); template <class T> random_access_iterator_tag iterator_category(const T*); template <class T, class Distance> T* value_type(const input_iterator<T,Distance>&); template <class T, class Distance> T* value_type(const forward_iterator<T,Distance>&); template <class T, class Distance> T* value_type(const bidirectional_iterator<T,Distance>&); template <class T, class Distance> T* value_type(const random_access_iterator<T,Distance>&); template <class T> T* value_type(const T*); template <class T, class Distance> Distance* distance_type(const input_iterator<T,Distance>&); template <class T, class Distance> Distance* distance_type(const forward_iterator<T,Distance>&); template <class T, class Distance> Distance* distance_type(const bidirectional_iterator<T,Distance>&); template <class T, class Distance> Distance* distance_type(const random_access_iterator<T,Distance>&); template <class T> ptrdiff_t* distance_type(const T*); // subclause 24.2.6, iterator operations: template <class InputIterator, class Distance> void advance(InputIterator& i, Distance n); template <class InputIterator, class Distance> void distance(InputIterator first, InputIterator last, Distance& n); // subclause 24.3, predefined iterators: template <class BidirectionalIterator, class T, class Reference, class Distance = ptrdiff_t> class reverse_bidirectional_iterator; template <class BidirectionalIterator, class T, class Reference, class Distance> bool operator==( const reverse_bidirectional_iterator <BidirectionalIterator,T,Reference,Distance>& x, const reverse_bidirectional_iterator <BidirectionalIterator,T,Reference,Distance>& y); 24–10 Iterators library DRAFT: 28 April 1995 24.1.6 Iterator tags template <class RandomAccessIterator, class T, class Distance = ptrdiff_t> class reverse_iterator : public random_access_iterator<T,Distance>; template <class RandomAccessIterator, class T, class Distance> bool operator==( const reverse_iterator<RandomAccessIterator,T,Reference,Distance>& x, const reverse_iterator<RandomAccessIterator,T,Reference,Distance>& y); template <class RandomAccessIterator, class T, class Distance> bool operator<( const reverse_iterator<RandomAccessIterator,T,Reference,Distance>& x, const reverse_iterator<RandomAccessIterator,T,Reference,Distance>& y); template <class RandomAccessIterator, class T, class Distance> Distance operator-( const reverse_iterator<RandomAccessIterator,T,Reference,Distance>& x, const reverse_iterator<RandomAccessIterator,T,Reference,Distance>& y); template <class RandomAccessIterator, class T, class Distance> reverse_iterator<RandomAccessIterator,T,Reference,Distance> operator+ (Distance n, const reverse_iterator<RandomAccessIterator,T,Reference,Distance>& x); template <class Container> class back_insert_iterator; template <class Container> back_insert_iterator<Container> back_inserter(Container& x); template <class Container> class front_insert_iterator; template <class Container> front_insert_iterator<Container> front_inserter(Container& x); template <class Container> class insert_iterator; template <class Container, class Iterator> insert_iterator<Container> inserter(Container& x, Iterator i); // subclauses 24.4, stream iterators: template <class T, class Distance = ptrdiff_t> class istream_iterator; template <class T, class Distance> bool operator==(const istream_iterator<T,Distance>& x, const istream_iterator<T,Distance>& y); template <class T> class ostream_iterator; template<class charT, class traits = ios_traits<charT> > class istreambuf_iterator; template <class charT, class traits = ios_traits<charT> > bool operator==(istreambuf_iterator<charT,traits>& a , istreambuf_iterator<charT,traits>& b ); template <class charT, class traits = ios_traits<charT> > bool operator!=(istreambuf_iterator<charT,traits>& a , istreambuf_iterator<charT,traits>& b ); template <class charT, class traits = ios_char_traits<charT> > class ostreambuf_iterator; output_iterator iterator_category (const ostreambuf_iterator&); template<class charT, class traits = ios_char_traits<charT> > bool operator==(ostreambuf_iterator<charT,traits>& a, ostreambuf_iterator<charT,traits>& b); template<class charT, class traits = ios_char_traits<charT> > bool operator!=(ostreambuf_iterator<charT,traits>& a, ostreambuf_iterator<charT,traits>& b); } 24.2 Iterator primitives DRAFT: 28 April 1995 Iterators library 24–11 [lib.iterator.primitives] 24.2 Iterator primitives 1 To simplify the task of defining the iterator_category, value_type and distance_type for user def inable iterators, the library provides the following predefined classes and functions: [lib.std.iterator.tags] 24.2.1 Standard iterator tags namespace std { struct input_iterator_tag {}; struct output_iterator_tag {}; struct forward_iterator_tag {}; struct bidirectional_iterator_tag {}; struct random_access_iterator_tag {}; } [lib.basic.iterators] 24.2.2 Basic iterators namespace std { template <class T, class Distance = ptrdiff_t> struct input_iterator {}; struct output_iterator{}; template <class T, class Distance = ptrdiff_t> struct forward_iterator {}; template <class T, class Distance = ptrdiff_t> struct bidirectional_iterator {}; template <class T, class Distance = ptrdiff_t> struct random_access_iterator {}; } 1 [Note: output_iterator is not a template because output iterators do not have either value type or dis- tance type defined. —end note] [lib.iterator.category] 24.2.3 iterator_category template <class T, class Distance> input_iterator_tag iterator_category(const input_iterator<T,Distance>&); Returns: input_iterator_tag(). output_iterator_tag iterator_category(const output_iterator&); Returns: output_iterator_tag(). template <class T, class Distance> forward_iterator_tag iterator_category(const forward_iterator<T,Distance>&); Returns: forward_iterator_tag(). template <class T, class Distance> bidirectional_iterator_tag iterator_category(const bidirectional_iterator<T,Distance>&); Returns: bidirectional_iterator_tag(). template <class T, class Distance> random_access_iterator_tag iterator_category(const random_access_iterator<T,Distance>&); 24–12 Iterators library DRAFT: 28 April 1995 24.2.3 iterator_category Returns: random_access_iterator_tag(). template <class T> random_access_iterator_tag iterator_category(const T*); Returns: random_access_iterator_tag(). [lib.value.type] 24.2.4 value_type template <class T, class Distance> T* value_type(const input_iterator<T,Distance>&); template <class T, class Distance> T* value_type(const forward_iterator<T,Distance>&); template <class T, class Distance> T* value_type(const bidirectional_iterator<T,Distance>&); template <class T, class Distance> T* value_type(const random_access_iterator<T,Distance>&); template <class T> T* value_type(const T*); Returns: (T*)(0). [lib.distance.type] 24.2.5 distance_type template <class T, class Distance> Distance* distance_type(const input_iterator<T,Distance>&); template <class T, class Distance> Distance* distance_type(const forward_iterator<T,Distance>&); template <class T, class Distance> Distance* distance_type(const bidirectional_iterator<T,Distance>&); template <class T, class Distance> Distance* distance_type(const random_access_iterator<T,Distance>&); Returns: (Distance*)(0). template <class T> ptrdiff_t* distance_type(const T*); Returns: (ptrdiff_t*)(0). [lib.iterator.operations] 24.2.6 Iterator operations 1 Since only random access iterators provide + and - operators, the library provides two template functions advance and distance. These functions use + and - for random access iterators (and are, therefore, constant time for them); for input, forward and bidirectional iterators they use ++ to provide linear time implementations. template <class InputIterator, class Distance> void advance(InputIterator& i, Distance n); Requires: n may be negative only for random access and bidirectional iterators. Effects: Increments (or decrements for negative n) iterator reference i by n. template <class InputIterator, class Distance> void distance(InputIterator first, InputIterator last, Distance& n); [...]... reverse_iterator& operator-=(Distance n); Reference operator[](Distance n); template bool operator==( const reverse_iterator& x, const reverse_iterator& y); template ... public random_access_iterator { protected: RandomAccessIterator current; public: reverse_iterator(); explicit reverse_iterator(RandomAccessIterator x); RandomAccessIterator base(); Reference operator*(); // explicit reverse_iterator& reverse_iterator reverse_iterator&... template void push_heap(RandomAccessIterator first, RandomAccessIterator last, Compare comp); template void pop_heap(RandomAccessIterator first, RandomAccessIterator last); template void pop_heap(RandomAccessIterator first, RandomAccessIterator last, Compare comp); template... make_heap(RandomAccessIterator first, RandomAccessIterator last); template void make_heap(RandomAccessIterator first, RandomAccessIterator last, Compare comp); template void sort_heap(RandomAccessIterator first, RandomAccessIterator last); template void sort_heap(RandomAccessIterator first, RandomAccessIterator... sorting: template void sort(RandomAccessIterator first, RandomAccessIterator last); template void sort(RandomAccessIterator first, RandomAccessIterator last, Compare comp); template void stable_sort(RandomAccessIterator first, RandomAccessIterator last); template void... operator . reverse_iterator<RandomAccessIterator,T ,Reference, Distance>& x, const reverse_iterator<RandomAccessIterator,T ,Reference, Distance>& y); template <class RandomAccessIterator, class T, class Distance> Distance. <class RandomAccessIterator, class T, class Reference = T&, class Distance = ptrdiff_t> class reverse_iterator : public random_access_iterator<T,Distance> { protected: RandomAccessIterator. const; reverse_iterator<RandomAccessIterator,T ,Reference, Distance>& operator-=(Distance n); Reference operator[](Distance n); template <class RandomAccessIterator, class T, class Reference, class Distance> bool operator==( const