STL Source Code Analysis--Houtie
Although many languages now support the identification of parameter types, this feature is not supported by C + +.
But there are some tricks that we can use to make C + + automatically discriminate the parameter types.
We all know that in template classes and template functions We do not specify the type of the parameter, and the compiler will automatically determine the type of the parameter.
So we were wondering if we could get the type extracted from the compiler runtime?
can be implemented by inline type.
#include <iostream>using namespacestd;template<classT>structmyiter{typedef T VALUE_TYPE; //declare inline type as Value_typet*ptr; Myiter (T* p =0):p TR (p) {} T&operator*()Const{return*ptr;}}; Template<classI>TypeName I::value_type//The above line tells the compiler this type, otherwise func cannot returnfunc (I ite) {return*ite;}intMainintargcConst Char*argv[]) {Myiter<int> Ite (New int(8)); cout<< func (ITE) <<Endl; //8 return 0;}~
The Func function here can successfully extract the value_type.
But there's also a hidden trap.
This is problematic when the iterator is a native pointer, because the native pointer does not have an inline type.
This requires the template to write a biased version of this type.
1#include <iostream>2 using namespacestd;3 4Template <classT>5 structmyiter{6 typedef T VALUE_TYPE;7 //declare inline type as Value_type8t*ptr;9Myiter (t* p =0):p TR (p) {}Tent&operator*()Const{return*ptr;} One }; A -Template <classI> - structiterator_traits_1{ the typedef typename I::value_type Value_type; - }; - //encapsulates the myiter to get its inline type - +Template <classT> - structIterator_traits_1<t*>{ + typedef T Value_type; A }; at //define the type of the native pointer - -Template <classI> -TypeName Iterator_traits_1<i>:: Value_type - //tells the compiler that the type returned by the following function - func (I ite) in{return*ite;} - to intMainintargcConst Char*argv[]) + { -myiter<int> Ite (New int(8)); thecout << func (ITE) <<Endl; * //returns 8 $ intA =5;Panax Notoginseng int*b = &A; -cout << func (b) <<Endl; the //returns 5 + return 0; A}
Here we have the original type Myiter another layer of encapsulation, the advantage is that the following function can also be used for the native pointer.
In order to be able to use the native pointer, we also wrote a biased version.
The difference between the specialized version and the biased version is that the specialized version is only for a specific type implementation.
The partial version is for a specific set of type specificity, more general.
Here we are generating a partial version for all the native pointers.
The role of traits here is very important, and its role is not only compatible with each type, but also a "type extractor".
One point to note is that in order to be compatible with traits, there must be a relevant inline type definition, which is critical in the STL iterator.
- Iterator partial source re-column
1 //STL All iterator types2 structInput_iterator_tag {};3 structOutput_iterator_tag {};4 structForward_iterator_tag {}: PublicInput_iterator_tag {};5 structBidirectional_iterator_tag: PublicForward_iterator_tag {};6 structRandom_access_iterator_tag: PublicBidirectional_iterator_tag {};7 8Template <classCategory,classTclassDistance = ptrdiff_t,classPointer = t*,classReference = t&>9 structiterator{Ten typedef Category Iterator_category; One typedef T VALUE_TYPE; A typedef Distance DIFFERENCE_TYPE; - typedef Pointer Pointer; - typedef Reference Reference; the }; - - //type extraction Machine traits -Template <classIterator> + structiterator_traits{ - typedef typename Iterator::iterator_category iterator_category; + typedef typename Iterator::value_type Value_type; A typedef typename Iterator::d ifference_type defference_type; at typedef typename Iterator::p ointer pointer; - typedef typename Iterator::reference Reference; - }; - - //biased version for native pointers -Template <classT> in structIterator_traits<t*>{ - typedef random_access_iterator_tag Iterator_category; to typedef T VALUE_TYPE; + typedef ptrdiff_t DIFFERENCE_TYPE; -typedef t*pointer; thetypedef t&reference; * }; $ Panax Notoginseng //This function makes it easy to determine the type of an iterator (category) -Template <classIterator> theInline TypeName Iterator_traits<iterator>:: Iterator_category +Iterator_category (Constiterator&) A { thetypedef TypeName Iterator_traits<iterator>:: iterator_category category; + returncategory (); - } $ $ //This function makes it easy to determine the distance_type of an iterator -Template <classIterator> -Inline typename Iterator_traits<iterator>::d ifference_type* theDistance_type (Constiterator&) - {Wuyi returnStatic_cast<typename iterator_traits<iterator>::d ifference_type*> (0); the } - Wu //This function makes it easy to determine the value_type of an iterator -Template <classIterator> AboutInline TypeName iterator_traits<iterator>::value_type* $Value_type (Constiterator&) - { - returnStatic_cast<typename iterator_traits<iterator>::value_type*> (0); - } A + //The following is the whole set of distance functions the //the third parameter in the two __distance function has no practical meaning, just to discriminate between the overlapping - //Surrogate Type $Template <classInputiterator> theInline iterator_traits<inputiterator>::d ifference_type the __distance (inputiterator First, Inputiterator last, Input_iterator_tag) { theIterator_traits<inputiterator>::d ifference_type n =0; the while(Frist! =Last ) { -++first; ++N; in } the returnN; the } AboutTemplate <classRandomaccessiterator> theInline iterator_traits<randomaccessiterator>::d ifference_type the __distance (randomaccessiterator First, Randomaccessiteratoriterator last, the Random_access_iterator_tag) { + returnLast-First ; - } the BayiTemplate <classInputiterator> theInline iterator_traits<inputiterator>::d ifference_type the distance (inputiterator first, inputiterator last) - { - typedef TypeName theIterator_traits<inputiterator>:: iterator_category category; the return__distance (First, last, category ()); the}
View Code
With regard to these features, the use of STL in a large amount, to some extent, supplemented the shortcomings of C + +;
The most important thing is that these features help us to do a type of judgment when the program compiles, rather than writing a function to judge at run time.
Faster and more efficient.
C + +: Derivation of parametric types