C + + Learning -- templates and template classes

Keywords: C++

catalogue

1: Template function

one point one   General template function

1.2 specialized template function

  2: Template class

2.1 formwork

2.2 member template function

2.3 formwork specialization

2.3.1 template member function specialization

2.3.2 template specialization

3: Template class AutoPtr  

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;
	}

Posted by kaeserea on Tue, 16 Nov 2021 07:12:03 -0800