Why type extraction is required
We mentioned the iterator, which is a behavior similar to smart pointer, which is primarily used to access objects in STL containers, and does not expose the internal structure of the container, whereas the type of the object that the iterator refers to is the value type of the iterator; If we should get the value type of the object in the STL container in the actual project, we need to use the template in C + +, let's take a look at the following code:
Template <class t>void Func () { cout << "non-built-in type" << Endl;} Template <>void func<int> () { cout << "built-in int type" << Endl;}
We can derive parameters by means of specificity, and if we customize more than one type, we can only judge that they are built-in types unless we write out the specific versions of these custom types.
In this case, we introduced the inline type, defining the type that the iterator points to as value type in the class, and defining some other types, specifically the inline type of the iterator mentioned in the previous blog, iterator: https://www.cnblogs.com/cthon/p/9206262.html
typedef bidirectional_iterator_tag iterator_category; typedef T VALUE_TYPE; typedef PTR Pointer; typedef REF Reference; typedef __list_node<t>* LINK_TYPE; typedef size_t SIZE_TYPE; typedef ptrdiff_t DIFFERENCE_TYPE;
However, there is a gap, such as the following code:
Template <class t>struct myiter{ typedef T VALUETYPE; t* _ptr; Myiter (t* p = 0) : _ptr (P) {} t& operator* () { return *_ptr; }}; Template<class iterator>typename Iterator::valuetypefunc (Iterator it) { return *it;}
Although there seems to be no problem here, not all iterators have inline types, such as native pointers, because native pointers are not types, so we cannot define inline types for native pointers.
We can also look at the following example:
Here's the code first:
Vector code Template <class T, class Alloc = Alloc>class vector{public://vector inline type typedef t ValueType; typedef valuetype* Pointer; typedef const VALUETYPE* Constpointer; typedef valuetype* Iterator; typedef const VALUETYPE* Constiterator; typedef const VALUETYPE* Constpointer; typedef valuetype& Reference; typedef const valuetype& Constreference; typedef size_t SizeType; typedef size_t Differencetype;public:vector (): _start (0), _finish (0), _endofstora GE (0) {}//vector () Iterator Begin () {return _start; } Iterator End () {return _finish; } constiterator Cbegin () const {return _start; } constiterator cend () const {return _finish; } valuetype& operator[] (const sizetype& N) {return * (_start + N); }//const valuetype&Operator[] (const sizetype& N) const//{//return * (_start + N); } void Pushback (const valuetype& x) {//Capacity expansion _checkcapacity (); Insert (_finish, x); } void Insert (Iterator pos,const valuetype& x) {//sizetype n = pos-_begin; ASSERT (Pos>=_start&&pos<=_finish); if (pos = = _finish) {Construct (_finish, x); _finish++; } else {//calculates the number of existing elements after the insertion point size_t Elemfront = _finish-pos; /* _finish++;*/for (int i = 0; i < Elemfront; i++) {Iterator Copypos = _finish I Construct (Copypos, * (CopyPos-1)); } _finish++; Construct (pos, x); }}protected:typedef Simplealloc<valuetype, alloc> dataallocator; Iterator _start; Iterator _finish; Iterator _endofstorage;protected:void _checkcapacity () { if (_finish = = _endofstorage) {//Space is full, open space size_t oldsize = _finish-_start; size_t NewSize = oldsize * 2 + 3; t* _tmp = dataallocator::allocate (NewSize); Opens new space for (size_t i = 0; i < oldsize; i++) {//copies the members of the original array _tmp[i ] = _start[i]; }//change parameter swap (_start, _tmp); _finish = _start + oldsize; _endofstorage = _start + NewSize; Free space dataallocator::d eallocate (_tmp, oldsize); }}};void Testvector () {vector<int> v1; V1. Pushback (1); V1. Pushback (2); V1. Pushback (3); V1. Pushback (4); V1. Pushback (5); V1. Pushback (6); Vector<int>::iterator it =v1. Begin (); while (it! = v1. End ()) {cout << *it << ""; it++; } cout << "Distance?" << Distance (v1. Begin (), v1. End ()) << Endl;} The distance between two iterators for a function//common type of two iteratorsThe function template <class inputiterator>inline size_t __distance (inputiterator First, Inputiterator last, Inputiteratortag) {size_t n = 0; while (first! = last) {++first; ++n; } return n;} The Randomaccessiteratortag type is a function of finding the distance between two iterators, template <class randomaccessiterator>inline size_t __distance ( Randomaccessiterator First, Randomaccessiterator last, Randomaccessiteratortag) {size_t n = 0; n + = Last-first; return n;} The function of finding the distance between two iterators is template <class inputiterator>inline size_t Distance (inputiterator First, Inputiterator last) {R Eturn __distance (First, last,inputiterator::iteratorcategory ()); /*return __distance (First, last,iteratortraits<inputiterator>::iteratorcategory ()); */}
If there are only inline types, the following happens:
A detailed explanation is given in the figure.
The native pointer is supposed to be the randomaccessiterator in the iterator, because the type cannot be defined for the native pointer, so we have no way to get the iterator to the native pointer, and then the type extraction comes out:
Type extraction template <class iterator>struct iteratortraits{typedef typename Iterator::iteratorcategory Iteratorcategory; typedef typename ITERATOR::VALUETYPE ValueType; typedef typename Iterator::D ifferencetype differencetype; typedef typename Iterator::P ointer Pointer; typedef typename Iterator::reference reference;};/ /native pointer type extraction template <class t>struct iteratortraits<t*>{typedef randomaccessiteratortag iteratorcategory; typedef T VALUETYPE; typedef ptrdiff_t DIFFERENCETYPE; typedef t* Pointer; typedef t& reference;};/ /For const t* Type extraction template <class t>struct iteratortraits<const t*>{typedef randomaccessiteratortag Itera Torcategory; typedef T VALUETYPE; typedef ptrdiff_t DIFFERENCETYPE; typedef t* Pointer; typedef t& Reference;};
&NBSP;
At this point, we can invoke the correct __distance function.
The design pattern of the type extraction improves the reusability of the Code, and in the example above, it improves the performance of the code by extracting the different iterator types to invoke the __distance function of the different iterators.
Reference: http://www.cnitblog.com/weitom1982/archive/2008/12/19/7889.html
C + + Extraction technology (traits)