Reference book STL Source Analysis
STL mainly learns the following parts:
I. Containers
1. Sequential containers
vector list deque
2. Associated Container, Red-Black Tree BST
set multiset map multimap//observer mode
3. Container adapter deque
stack queue priority_queue
II. Generic Algorithms
find sort
III. Iterators
Container: iterator reverse_iterator
const_iterator const_reverse_iterator
Five iterators
Input-Output Forward Bidirectional Random Access
Three types
1. Reverse
2. Insertion type
3. Flow pattern
4. Function object imitation function //greater less
Two species
Univariate function object
2. Binary Function Objects
V. Adapter bind2nd not1
VI. Space Configurator
Level 1 Space Configurator
2. Secondary Space Configurator
----------------------------------------
Preface: What does this blog want to write?
Following the idea of STL Source Analysis, I design iterators in list and vector, encounter problems, solve problems, and then summarize and analyze the source code.
But we need to understand the template, because STL uses a large number of templates, the concept of template is simple to use, template specialization (partial specialization, complete specialization); the type of iterator, the relationship between several iterators, analysis of the source code iterator, extraction of traits programming.
Summary of the book: Read it several times to understand:
It is the responsibility of the iterator to design the corresponding type of iterator.
It is the responsibility of the container to design appropriate iterators.
Only the container itself knows what iterators should be designed to visit itself and perform the various behaviors (forward, backward, value, member) that iterators should have.
As for the algorithm, it can be developed independently of the container iterator, as long as the iterator is designed as the external interface.
Trats programming techniques are widely used in STL. It makes use of "embedded gender" programming skills and compiler template parameter derivation function to enhance the ability of type authentication that c++ fails to provide.
Make up for the fact that c++ is not a strongly typed language.
Understanding traits programming is the key to open STL source profiling.
I. Relations of several iterators:
1. The corresponding type of iterator:
"What is the iterator type? Answer: The type of object that an iterator refers to is one of them (that is, the type of object that an iterator refers to)"
There are five types of iterators:
value_type * Value type: Type of object referred to by iterator
difference_type: Used to indicate the distance between two iterators
reference_type.Reference type:
Pointer type const_pointer_type Constant pointer type
iterator_category: Iterator type (divided into the following five types)
STL Source Analysis is a book written by Taiwan compatriots, so some words in the book feel awkward to read. For example, "Type of Object" is "Type of Object" in the book.
2. Five Iterators
Iterators are classified into five categories according to their movement characteristics and action actions.
input_iterator
output iterator
Forward Iterator
Bidirectional Iterator
Random Access Iterator
Relationships among five iterators: as shown in Figure 126 of STL Source Analysis
The arrows in the figure represent inheritance relationships, and you can see the hierarchical inheritance relationships of the five iterators.
What is common inheritance? "One" means! What is private inheritance? "Combination"...
3. Iterators in containers:
hashtable slist: forward iterator
Listmap set: bidirectional iterator
vector dequeue: Random iterator
(Understandably, the iterator in the container is three of the five iterators, because the forward iterator inherits the input and output iterators, so these three are enough.)
(Or that sentence: "It is the responsibility of the iterator to design the corresponding type of iterator. It is the responsibility of the container to design an appropriate iterator.
2. Designing iterators by oneself:
1. Define itreator as a tag category
//Create your own header file iterator.h struct input_iterator_tag{}; struct output_iterator_tag{}; struct forward_iterator_tag : public input_iterator_tag { }; struct bidirectional_iterator_tag : public forward_iterator_tag { }; struct random_access_iterator_tag : public bidirectional_iterator_tag { };
2. Define the iterator type:
//Written in iterator.h /* The following template outlines the template type: _Cate : iterator_category Iterator types (divided into the following five types) _Ty: value_type Value type: The type of the object that the iterator refers to _Dist:difference_type Difference type: Used to indicate the distance between two iterators _P : pointer_type Pointer type const_pointer_type constant pointer type _ref:reference_type Reference type: */ template<class _Cate,class _Ty,class _Dist class _P = _Ty*,class _Ref = _Ty&> //Defining an iterator requires five corresponding types: an iterator type value difference pointer reference struct iterator { //Rename typedef for five corresponding types of iterators: typedef _Cate iterator_category; typedef _Ty value_type; typedef _Dist difference_type; typedef _P pointer; typedef _Ref reference; }
3. Define the iterator in the container: bidirectional random forward:
Designing three classes, inheriting iterator classes altogether, and giving the logo of iterator
//Written in iterator.h template<class _Ty,class _Dist> //Forward iterator class _Forit:public iterator<forward_iterator_tag,_Ty,_Dist> {}; template<class _Ty,class _Dist> //Bidirectional Iterator class _BIDrit:public iterator<bidirectional_iterator_tag,_Ty,_Dist> {}; template<class _Ty,class _Dist> //RadomAccessIterator class _Ranrit:public iterator<random_access_iterator_tag,_Ty,_Dist> {};
4. Designing your own list
Of course, it's not complete here, it's only about iterators; there are many functions missing: insert, delete, construct...
//Write it under zdw_list.h namespace zdw { template<class _Ty> class list //Designing a linked list, node class, iterator class { private: struct _node; typedef _node* nodeptr; struct _node { nodeptr pre; nodeptr next; _Ty value; //Value of Node }; public: class const_iterator:public zdw::_Bidit<_Ty,int> //Inheritance bidirectional iterator {}; class iterator:public const_iterator {}; }; }
This is written in namespace to prevent naming contamination and use your own naming.
4. Design your own vector
//zdw_vector.h file design a vector namespace zdw { template<class _Ty> class vector { public: class const_iterator:public zdw::_Ranrit<_Ty,int> //random access iterators {}; class iterator:public const_iterator {}; }; }
6. Design the advance d function of the iterator: the movement of the iterator
Think: Write advance again to get the iterator type? That's the point of the book: Type Extraction Trats Programming Skills
Depending on the container, the iterator moves differently:
Forward iterators (such as single-linked lists): need to move step by step.
Bidirectional iterators (such as double-linked lists): judging whether to move forward or backward
Random iterators (such as vector s arrays): step-by-step straight across
//In iterator.h template<class _II,class _Dist> void _advance(_II &i,_Dist n,input_iterator_tag)//Input iterator: { while (n--) ++i;//You can only walk one by one. } template<class _II,class _Dist> void _advance(_II &i,_Dist n,bidirectional_iterator_tag)//Bidirectional Iterator { if (n >= 0) while (n--) ++i; //To judge positive and negative values else while (n++) --i; } template<class _II,class _Dist> void _advance(_II &i,_Dist n,random_accessl_iterator_tag)//RadomAccessIterator { i += n; //Random iterators can be used directly+ }
But the final advance d design is a difficult point:
Design 1: Can't solve the problem, error, pass out
template<class _II,class _Dist> void advance(_II &i,_Dist n) //Key and Difficult Points in the Design of this Function { //How does advance call the moving function of the _advance (_II &i, _Dist n, input_iterator_tag) bidirectional iterator? }
Design 2: Consider the iterator type as a type parameter, but there are still problems.
template<class _II,class _Dist> //Type plus () means that this is an object void advance(_II &i,_Dist n,input_iterator_tag() ) //However, how does the system know from the type of _II iterator that it is input_iterator_tag { _advance(i,n,input_iterator_tag()) }
Design 3: // This is the focus of today's work: Type extraction does not write the results here, it needs to be analyzed step by step.
7. Write an example of type extraction:
I understand type extraction: to get the type of template, how to get it? Add an intermediate layer, or that principle, "The problem in computer can be added an intermediate layer, where the intermediate layer is the extraction extraction structure."
(1) An imperfect program: interface reuse can not be achieved:
template<class _Ty> class SeqList { public: typedef _Ty value_type; private: _Ty data[10]; int cursize; public: SeqList():cursize(0){}; ~SeqList(){}; void push(const _Ty &x) { data[cursize++] = x; } }; template<class Container> void Append(Container &seq) { int x; cin>>x; seq.push(x); } int main() { SeqList<int> seq; Append(seq); }
The problem with this program is that if we SeqList < double > seq, then x in the Append function needs to be changed to double.
(2) Increase type extraction mechanism:
template<class _Ty> class SeqList //Let's design a sequence table. { public: typedef _Ty value_type; private: _Ty data[10]; int cursize; public: SeqList():cursize(0){}; ~SeqList(){}; void push(const _Ty &x) { data[cursize++] = x; } }; template<class Container> //The extraction mechanism of the middle layer to get the data type in the current container struct traits_seq { typedef typename Container::value_type value_type; }; template<class Container> void Append(Container &seq) { typename traits_seq<Container>::value_type x; cin>>x; seq.push(x); } int main() { SeqList<int> seq; Append(seq); }
8. Back to the extraction of advance d function in iterator
template<class Iterator> struct itreator_traits { typedef typename Iterator::iterator_category iterator_category; typedef typename Iterator::value_type value_type; typedef typename Iterator::difference_type difference_type; typedef typename Iterator::pointer pointer; typedef typename Iterator::reference reference; }
9. Writing Iterator Method: Overload ++ -- Pre-post, etc.
10. Solve the problem that ordinary pointer cannot be extracted
Native Type Pointer: A Random Iterator
Processing of pointers: partial specialization and complete specialization of template functions
//Several examples of specialization: template<class T> class C{}; //No specialization template<class T> class C<T*>{}; //partial specialization template<class T> class C<const T*>{}; //partial specialization template<> class C<char *>{}; //complete specialization
I was impressed by what the teacher said at that time.
Template specialization is like looking for objects:
Complete specialization is just graduated young people, "I want to marry Bai Fumei, cute and lovely Dili Reba."
Part of specialization is "I want to find beautiful on the line";
No specialization is: "I marry a woman, it's OK!"
//Rewriting Extraction Structures template<class T> struct iterator_traits<const T*> { iterator_traits(){}; typedef random_access_iterator_tag iterator_category; typedef T value_type; typedef int difference_type; typedef T* pointer; typedef T& reference; }
11.sgi and vs
12. Implementation of distance function: find an example between two iterators
template<class _II> typename iterator_traits<_II>::difference_type __distance(_II _First,_II _Last,input_iterator_tag) //Input Iterator { typename iterator_traits<_II>::difference_type n = 0; for(,_First != Last;++_First,++n); return n; } template<class _RAI> typename iterator_traits<_RAI>::difference_type __distance(_RAI _First,_RAI _Last,random_access_iterator_tag) //RadomAccessIterator { return _Last - _First; } template<class _II> typename iterator_traits<_II>::difference_type distance(_II _First,_II _Last) //Final distance { return __distance(_First,_Last,iterator_category(_First)); }
11. Summary:
It is the responsibility of the iterator to design the corresponding type of iterator.
It is the responsibility of the container to design appropriate iterators.
Only the container itself knows what iterators should be designed to visit itself and perform the various behaviors (forward, backward, value, member) that iterators should have.
As for the algorithm, it can be developed independently of the container iterator, as long as the iterator is designed as the external interface.
Trats programming techniques are widely used in STL. It makes use of "embedded gender" programming skills and compiler template parameter derivation function to enhance the ability of type authentication that c++ fails to provide.
Make up for the fact that c++ is not a strongly typed language.
Understanding traits programming is the key to open STL source profiling.
12.iterator full source code:
// Excerpts from SGI STL <stl_iterator.h> // Five types of iterators struct input_iterator_tag {}; struct output_iterator_tag {}; struct forward_iterator_tag : public input_iterator_tag {}; struct bidirectional_iterator_tag : public forward_iterator_tag {}; struct random_access_iterator_tag : public bidirectional_iterator_tag {}; // In order to avoid any omission when writing code, the self-developed iterator is best inherited from the following std::iterator template <class Category, class T, class Distance = ptrdiff_t,class Pointer = T*, class Reference = T&> struct iterator { typedef Category iterator_category; typedef T value_type; typedef Distance difference_type; typedef Pointer pointer; typedef Reference reference; }; // "Juicer" traits template <class Iterator> struct iterator_traits { typedef typename Iterator::iterator_category iterator_category; typedef typename Iterator::value_type value_type; typedef typename Iterator::difference_type difference_type; typedef typename Iterator::pointer pointer; typedef typename Iterator::reference reference; }; // The traits partial specialization version (partial specialization) is designed for native pointer. template <class T> struct iterator_traits<T*> { typedef random_access_iterator_tag iterator_category; typedef T value_type; typedef ptrdiff_t difference_type; typedef T* pointer; typedef T& reference; }; // The traits partial specialization version (partial specialization) is designed for native pointer-to-const. Taiwan compatriots call partial specialization template <class T> struct iterator_traits<const T*> { typedef random_access_iterator_tag iterator_category; typedef T value_type; typedef ptrdiff_t difference_type; typedef const T* pointer; typedef const T& reference; }; // This function can easily determine the type of an iterator. template <class Iterator> inline typename iterator_traits<Iterator>::iterator_category iterator_category(const Iterator&) { typedef typename iterator_traits<Iterator>::iterator_category category; return category(); } // This function can easily determine the distance type of an iterator. template <class Iterator> inline typename iterator_traits<Iterator>::difference_type* distance_type(const Iterator&) { return static_cast<typename iterator_traits<Iterator>::difference_type*>(0); } // This function can easily determine the value type of an iterator. template <class Iterator> inline typename iterator_traits<Iterator>::value_type* value_type(const Iterator&) { return static_cast<typename iterator_traits<Iterator>::value_type*>(0); } // Here's the whole set of distance functions template <class InputIterator> inline iterator_traits<InputIterator>::difference_type __distance(InputIterator first, InputIterator last,input_iterator_tag) { iterator_traits<InputIterator>::difference_type n = 0; while (first != last) { ++first; ++n; } return n; } template <class RandomAccessIterator> inline iterator_traits<RandomAccessIterator>::difference_type __distance(RandomAccessIterator first, RandomAccessIterator last,random_access_iterator_tag) { return last - first; } template <class InputIterator> inline iterator_traits<InputIterator>::difference_type distance(InputIterator first, InputIterator last) { typedef typename iterator_traits<InputIterator>::iterator_category category; return __distance(first, last, category()); } // Here's the whole set of advance d functions template <class InputIterator, class Distance> inline void __advance(InputIterator& i, Distance n,input_iterator_tag) { while (n--) ++i; } template <class BidirectionalIterator, class Distance> inline void __advance(BidirectionalIterator& i, Distance n,bidirectional_iterator_tag) { if (n >= 0) while (n--) ++i; else while (n++) --i; } template <class RandomAccessIterator, class Distance> inline void __advance(RandomAccessIterator& i, Distance n,random_access_iterator_tag) { i += n; } template <class InputIterator, class Distance> inline void advance(InputIterator& i, Distance n) { __advance(i, n, iterator_category(i)); }
--------------------------------------------
C++ thought: simulate reality, simulate and similar! Programming is to reflect the world in the computer!