Today finally read the "STL Source Analysis", recently busy two games of various documents, there is no time to write things, take advantage of the strength of the reading, the owed to fill up.
The iterator model is described in Design patterns as follows: Provides a way to sequentially search through the elements contained in a polymer without exposing the internal structure of the polymer. In STL, iterator plays a role in connecting container and algorithms, and the STL find () function below shows iterator's connection between container and algorithm.
Template <classclass t>const t& value) { while ( First! = Last && *first! = value) + + first; return First ;}
From the code we can see that the Find () function accepts two "smart pointers" with pointer behavior, they "point" to the object we want to work with, can get the point by the dereference operation (* operation), and can be implemented by the + + operation to point to the next function. As we now have an array (container) int a[5] = {1,2,3,4,5}; We can use Find () this way.
int*= Find (a,a+5,3// output 3
So, iterator is the function that implements the pointer. However, if our data container becomes set, because the internal structure of the set is rb-tree,++ operation can not implement the function that we expect to point to the next element like the native pointer, if you want the find () function to work successfully on the set, We have to encapsulate the "smart Pointe" interface provided by the set to achieve our desired functionality (such as picking the element that the iterator points to, the member access operation, the + + operation pointing to the next element, and so on). To hide the implementation details of the container, iterators are developed by the designers of each container, and each STL container provides a dedicated iterator.
Sometimes we need to know the type of the object that iterator is referring to and define the object. But it's not a simple thing. The traits programming technique is used to obtain the type of the object that the iterator refers to.
If you want to get the type of the object you are referring to, the first thing we think about is pushing the implementation using the template parameters.
Template <classclass t>void Func_impl (I iter, T t) { T tmp; // Do something }template<class i>void func (I iter) { *iter); simply call Func_impl, by passing in the *iter, through the template pushed to, you can know the type of ITER }
However, one drawback of this method is that "template parameter derivation" can only deduce parameters, but not the function return value, so the STL uses the inline type to implement the derivation function return value type.
Template <classT>structmyiter {typedef T value_type; T*ptr; Myiter (T* p =0): PTR (P) {} T&operator*()Const{return*ptr;}}; Template<classI>TypeName I:: Value_type//determines the return type of a function through an inline type, whereTypeName is used to tell the compiler that Value_type is a type, not a member function within I ordata memberfunc (I ite) {return*ite;} Myiter<int> Ite (New int(8));//determined the Myiter inline type Value_typecout << func (ITE);
For generalization, STL must accept a native pointer as an iterator, the above method cannot handle the case of native pointers, so STL uses the method of partial specialization to deal with the disadvantage of the above method.
Generics is defined by generic thinking as a special version that is designed to limit the condition of the template parameter further.
The above embedded type can be added a layer of indirection to change to the following:
template<class i>struct iterator_traits{ typedef typename I::value_type value_type;}; Template<class i>typename iterator_traits// I inline type value_type Func (I-tie) {return *ite;}
Adding a layer of indirection can be used to treat native pointers with a partial specificity. We define a iterator_traits version of two.
Template <class t>struct iterator_traits<t*>{ <class t> struct iterator_traits<const t*>{ typedef T value_type;}
This way, both the native pointer int* and the const int* can be extracted by iterator_traits to remove their correct value_type. Summing up, Iterator_traits is the use of embedded type and template parameter derivation, extracting the type of iterator object.
Iterator_traits not only can extract value_type, each iterator embedded five types, respectively asked Value_type,difference type, reference type, pointer type, Iterator_category, where iterator_category represents the classification of iterator. The iterators are divided into five categories, depending on the movement characteristics and execution operations:
Input iterator (read only), output iterator (write only), forward iterator (++only), bidirectional iterator (++,--), random Access iterator (covers all pointer operations p+n, etc.). Future advance algorithms will overload different implementation functions based on different iterator types to maximize efficiency!
Summing up, iterator provides an interface to traverse the container and hide the implementation details of the container as much as possible.
STL iterator and traits programming techniques