Review of C++ Template Initial Stage

Posted by bravo81 on Tue, 27 Aug 2019 11:58:13 +0200

This section mainly includes the following contents:

I. Generic Programming
Function Template
III. Class Template

 

I. Generic Programming

1. Concept: Writing generic type-independent code is a means of code reuse. Template is the basis of generic programming.

Function Template

1.Concept: Function templates represent a family of functions, which are type-independent, parameterized in use, and generate function specificity according to the type of argument.
//Type version.

2.format

template<typename T1, typename T2,......,typename Tn>
//Return value type function name (parameter list) {}

template <class T>
T Add(T a, T b)
{
	return a + b;
}

int main()
{

	int a = 10;
	int b = 20;
	cout << Add(a, b) << endl;
	cout << Add(1.0, 2.1) << endl;
	return 0;
}

Note: Typeename is used to define keywords for template parameters, and class can also be used (remember: struct cannot be used instead of class)

3. Principle

In the compiler compilation phase, for the use of template functions, the compiler needs to deduce and generate corresponding types of functions based on the type of arguments passed in for the purpose of providing
Call. For example, when using function templates with double type, the compiler determines T as double type by deducing the parameter type.
A code that deals specifically with the double type is generated, as is the case with character types.

4. Instance

(1) Concept: When using function templates with different types of parameters, it is called instantiation of function templates.

(2) Classification

[1] Implicit instantiation: Let the compiler deduce the actual type of template parameters based on arguments

template<class T>
T Add(const T& left, const T& right)
{
    return left + right;
}
int main()
{
    int a1 = 10, a2 = 20;
    double d1 = 10.0, d2 = 20.0;
    Add(a1, a2);
    Add(d1, d2);
    /*
    This statement cannot be compiled because during compilation, when the compiler sees the instantiation, it needs to deduce its parameter type.
    T is deduced to int by argument a1 and T is deduced to double type by argument d1, but there is only one T in the template parameter list.
    The compiler can't determine whether T should be identified as int or double type and the error will be reported here.
    Note: In templates, compilers generally do not perform type conversion operations, because once a problem is converted, the compiler needs to be a black pot.
    Add(a1, d1);
    */
    // There are two ways to deal with this situation: 1. Force transformation by users themselves; 2. Use explicit instantiation
    Add(a, (int)d);
    return 0;
}

[2] Explicit instantiation: the actual type of template parameter specified in <> after the function name

template<class T>
T Add(const T& a,const T& b)
{
	return a + b;
}

int main()
{
    int a = 10;
    double b = 20.0;
    // explicit instantiation
    Add<int>(a, b);
    return 0;
}

4. Matching Principle

[1] A non-template function can coexist with a function template with the same name, and the function template can also be instantiated into this non-template function.

[2] For non-template functions and function templates with the same name, if the other conditions are the same, non-template functions will be invoked preferentially when transferred without generating an instance from the template. For example, if a template can produce a function that matches better, the template will be selected.

[3] Template functions do not allow automatic type conversion, but ordinary functions can do automatic type conversion.

III. Class Template

1.format

template<class T1, class T2, ..., class Tn>
class Class template name
{
// Intra-class member definition
};

2.Give an example

// Dynamic Sequence Table
// Note: Vector is not a specific class, but a template for the compiler to generate specific classes based on the type being instantiated
template<class T>
class Vector
{
public:
	Vector(size_t capacity = 10)
		: _pData(new T[capacity])
		, _size(0)
		, _capacity(capacity)
	{}
	// Demonstration using destructors: Declare in classes and define outside classes.
	~Vector();
	void PushBack(const T& data);
	void PopBack();
	// ...
	size_t Size() { return _size; }
	T& operator[](size_t pos)
	{
		assert(pos < _size);
		return _pData[pos];
	}
private:
	T* _pData;
	size_t _size;
	size_t _capacity;
};
// Note: When a function in a class template is defined outside a class, a list of template parameters needs to be added.
template <class T>
Vector<T>::~Vector()
{
	if (_pData)
		delete[] _pData;
	_size = _capacity = 0;
}

2. Instance

Class template instantiation is different from function template instantiation. Class template instantiation needs to be followed by the name of class template <>, and then the type of instantiation can be placed in <>. Class template name is not a real class, but the result of instantiation is the real class.

// Vector class name, Vector < int > is the type
Vector<int> s1;
Vector<double> s2;

 

 

Topics: Programming