Rereading STL source code analysis: iterator

First on iterators:

Iterator object is a container for adhesion and algorithms, algorithm iterators as a medium, to the data container is calculated by the iterator.

Corresponding typed:

In the algorithm, when an element is operated in the vessel, and sometimes need to use a variable type in the container, such as a variable to a statement of the same class and the iterator pointed element, this processing time is very difficult.

The solution is to use a function that last parameter derivation:

template<class I>
inline void func(I iter)
{
  func_impl(iter,*iter);  
}

template <class I,class T>
void func_impl(I iter, T t)
{
  T tmp;      
}

 

Why do you want here func as an interface, but the actual operation to func_impl it?

This is because when we called, just want to pass iterators like that in such a way to call: func (& i); (& i equivalent to the iterator, i corresponds to the iterator points to the elements)

Whereas if not so used only one package:

template<class I,class T>
void func(I iter,T t)
{
  T tmp;  
}

 The problem with this is that every time you use func will be exposed iterator is pointing elements:

 func(&i,i);

 In this case func (& i) such calls are illegal.

 So add a layer package can make the call more in line with this design model, everything is hidden in the upcoming iterator or less.

 In fact, first of all func (& i) the first derivation of the func (int *) type I, and then transferred func_impl, when func_impl call the iterator type derived element pointed to via (& int, int) of the second parameter do int, and T is derived int, int then create tmp.

 

Traits programming techniques:

In the above discussion, the elements that implement the algorithm in the category declared inside the iterator points to function, but when the algorithm should return value is an iterator class pointed to elements of it?

In this case, it is impossible to achieve this functionality in the above manner.

Therefore bigwigs changed the thinking in the design of the iterator when the iterator within template declarations elements iterator type T pointed to value_type.

which is:

template<class T>
struct iterator
{
  typedef T value_type;
  T* ptr;
  .......    
}

  In this way, we can declare a variable in the form of iterator :: value_type of this variable is the type iterator points to other elements.

template<class I>
typename I::value_type
func(I ite)
{
  typename I::value_type tmp;  
}

  Thus, if we call the function func: pass an iterator to the inside, I will be judged not function template for the iterator type, and accordingly will return to judge the value typed iterator is pointing worth typed, because we inside the iterator it has been declared as a type of value_type. At the same time, we can also use variables declared inside an iterator iterator points to elements in this way.

  It looks very clever, but this method has a problem:

The problem is that if we are to derive the type of return value in this way and the type of algorithm declared inside an iterator points to an element of variables must be requested type it points to an element declared inside other iterator is value_type . But in this case the basic data types can not be done, because, like int *, char * these types, they are the basic data types, we can not artificially added typedef int value_type this declaration on the inside.

But as if this native int * pointers are excluded, take the iterator design still make sense to you?

 

In the above-mentioned problems, bigwigs to solve this problem by partial template specialization.

Partial template specialization is equivalent to providing a more specific template, during derived, actually closer to select the type of template to use derived, and therefore can be resolved for these versions of the original partial specialization pointer design.

Partial specialization meant to provide another template definition is itself still a template, but the template parameters further added conditions.

such as:

template <typename T>
class A 
{
	typedef T value_type;
};
template <typename T>
class A<T*>
{
	typedef T value_type;
};

  Wherein, when using A <int *> a; when, int * second template will be used, as compared to the first, compared to T * T closer to the form of the pointer.

Also note that the second can not exist alone, which means that if you delete a template will be the first error, partial specialization is dependent on the most common template that exists.


Now, we can introduce this part of the core, trait programming techniques:

First, look at this template class:

template<class I>
struct iterator_traits
{
  typedef typename I::value_type value_type;  
}

  This template is the most Mandarin template, which means that all the partial specialization of templates are based on this version.

Now look at the function func wrote earlier:

template <class I>
typename iterator_traits<I>::value_type
func(I ite)
{};

  Now, if we call the function func, and iterator passed automatically deduce the type I and type of return value is set inside value_type iterator class type.

In addition, we can use this template to design a number of partial specializations, such as T *, const T *, so that all types are unified to the next iterator, we can use an iterator to point to any element, the algorithm can be deduced corresponding type.

Category vlaue_type iterator is directed only to a corresponding element of the other type, there are many expanded described below.

 

Guess you like

Origin www.cnblogs.com/lxy-xf/p/11391189.html