catalogue
one point one General template function
1.2 specialized template function
2.3.1 template member function specialization
1: Template function
one point one General template function
Template refers to the programming with type as parameter in C + + programming language, which supports general programming. Using a template allows users to declare a general pattern for a class or function, so that the parameters and return values of some data members or member functions in the class can obtain any type. Let's take a simple example
#include<iostream> using namespace std; template<typename T> int compare(const T&v1, const T& v2) { if (v1 > v2) { return 1; } if (v1 < v2) { return -1; } else { return 0; } } int main() { const char* cp1 = "world", * cp2 = "hi"; int i1 = 1, i2 = 2; int a,b; a=compare(i1, i2); b=compare(cp1, cp2); cout << a << endl; cout << b << endl; }
The above example is in the form of a general template. You can call the same function for two different types of values. Template and typename are keywords. Typename can be replaced by class keyword. There is no difference between typename and class. The parameters in < > brackets are called template parameters. Template parameters are very similar to function parameters. Template parameters cannot be empty.
1.2 specialized template function
Function template specialization is to define the specific implementation version of the function template when the type parameter is instantiated as a specific type when a unified function template cannot work normally under all type instances. See the following example.
#include <iostream> using namespace std; template<typename T> T Max(T t1, T t2) { return (t1 > t2) ? t1 : t2; } typedef const char* CCP; template<> CCP Max(CCP s1, CCP s2) { //Use function overloading to realize the specialization of function template return (strcmp(s1, s2) > 0) ? s1 : s2; } int main() { //Call instance: int Max < int > (int, int) int i = Max(10, 5); //Call display specialization: const char * Max < const char * > (const char *, const char *) const char* p = Max("week", "good"); cout << "i:" << i << endl; cout << "p:" << p << endl; }
If the specialized version of the function template Max < T > when t is const char * is not given, when comparing the size of two strings, the size of the starting address of the string is compared, rather than the order of the contents of the string in the dictionary. Result display
2: Template class
2.1 formwork
Template class refers to the establishment of a general class whose data members, return value types and formal parameter types of member functions are not specified, but are represented by a virtual type. When a template class is used to define an object, the system will replace the virtual type in the class template with the type of the actual parameter, so as to realize the functions of different classes. Let's look at a template class test that compares the size of two elements
#include<iostream> using namespace std; template<typename T> class compare { public: T x, y; compare(T a, T b) { x = a; y = b; } T max() { return (x > y) ? x : y; } }; int main() { compare<int>com1(3, 7); cout << com1.max() << endl; compare<double>com2(12.34, 56.78); cout << com2.max() << endl; compare<char>com3('a', 'x'); cout << com3.max() << endl; }
Result display:
In this example, the compare template class is created, and three variables of type int, double and char are declared. All functions in the class are called. This is the basic use of the template class
2.2 member template function
You can also create templates in class members. Let's see a simple example
#include <iostream> using namespace std; class A { public: template<typename T> void compare(const T& v1, const T& v2) { if (v1 > v2) { cout << v1 << endl; } else { cout << v2 << endl; } } }; int main() { A a; a.compare(4, 6); a.compare("week", "good"); a.compare(5.5, 6.5);
Result display:
It can be seen that the template defined in the class can still make the parameters and return values of some data members or member functions in the class obtain any type.
2.3 formwork specialization
2.3.1 template member function specialization
Template member function specialization is roughly the same as template function specialization, except that one is defined in a class, and a class variable must be declared before use. We can modify the previous template function specialization slightly to complete a simple test
#include <iostream> using namespace std; class A { public: template<typename T> T Max(T t1, T t2) { return (t1 > t2) ? t1 : t2; } typedef const char* CCP; template<> CCP Max(CCP s1, CCP s2) { return (strcmp(s1, s2) > 0) ? s1 : s2; } }; int main() { A a; cout << a.Max(10, 5) << endl; cout << a.Max("week", "good") << endl; }
Result display:
Similarly, if the specialized version of the function template Max < T > when t is const char * is not given, when comparing the size of two strings, the size of the starting address of the string is compared, rather than the order of the contents of the string in the dictionary order.
2.3.2 template specialization
Class template specialization is similar to function template specialization, that is, the specific implementation of class template parameters under a specific type. The specialization of the template is basically the same. Let's take a look at an example
#include <iostream> using namespace std; template<typename T> class A { T num; public: A() { num = T(6.6); } void print() { cout << "num:" << num << endl; } }; template<>class A<char*> { const char* str; public: A() { str = "A special definition "; } void print() { cout << str << endl; } }; int main() { A<int> a1; //Show implicit instantiation of template arguments a1.print(); A<char*> a2;//Use specialized class templates a2.print(); }
Result display:
3: Template class AutoPtr
Since there is no automatic memory recovery mechanism in C + + language, programmers have to manually delete the memory every time they create a new one. However, some things are done after new. In the end, the old often forget to delete. Therefore, an intelligent pointer template class implemented by reference counting mechanism is provided. As shown below
Note here:
1. Whenever a reference is destroyed or rewritten, the reference count of the object it references will be reduced.
2. Whenever a reference is created or copied, the reference count of its referenced object will increase.
3. The initial reference count is 1.
4. When the reference of an object is 0, the object resource is destroyed.
5. In the case of multithreading, the increase and decrease must be atomic operations.
Object ownership:
1. Any object may have one or more owners.
2. As long as an object has at least one owner, it will continue to exist.
3. If an object has no owner, it can be destroyed.
Let's take a look at the implementation of the core code
The implementation of smart pointer constructor is as follows:
template < class T> AutoPtr<T>::AutoPtr(T * pData) { m_pData = pData; m_nUser = new int(1); //The initialization value is 1 }
Implementation of destructor:
template < class T> void AutoPtr<T>::decrUser() { ‐‐(*m_nUser); if ((*m_nUser) == 0) { delete m_pData; m_pData = 0; delete m_nUser; m_nUser = 0; } } template < class T> AutoPtr<T>::~AutoPtr() { decr() }
Overload of equal sign
template < class T> AutoPtr<T>&AutoPtr<T>::operator=(const AutoPtr<T>&h) { decrUser(); m_pData = h.m_pData; m_nUser = h.m_nUser; *m_nUser)++; }
->Overload of and *
T* operator‐> () { return m_pData; } T& operator*() { return *m_pData; }