hello, this is bangbang, let's talk about templates today
Table of contents
2.3 Instantiation of function templates
2.4 Matching principle of template parameters
3.1 Class template definition format
3.2 Class template instantiation
4. Non-type template parameters
5.1 Template specialization concept
5.2 Function template specialization
5.3 Class template specialization
6. Template separate compilation
6.1 What is separate compilation
6.2 Separate compilation of templates
1. Generic programming
How to implement a generic swap function?
Some friends may think of overloading with functions, as follows:
void Swap( int& left, int& right)
{
int temp = left;
left = right;
right = temp;
}
void Swap(double& left, double& right)
{
double temp = left;
left = right;
right = temp;
}
But there is a problem here, as long as my type does not conform to the function parameter, then I have to overload another copy, which is too troublesome!
1. The overloaded functions are only of different types, and the code reuse rate is relatively low. As long as a new type appears, the user needs to add the corresponding function2. The maintainability of the code is relatively low, one error may cause all overloads to be error
Can you tell the compiler a model and let the compiler use the model to generate code according to different types ?
2. Function templates
2.1 Function template concept
2.2 Function Template Format
template<typename T1, typename T2,......,typename Tn>
返回值 函数名(参数列表)
{}
The function template of the exchange function (the two parameter types are the same):
template<typename T>
void Swap(T& left, T& right)
{
T temp = left;
left = right;
right = temp;
}
2.3 Instantiation of function templates
1. Implicit instantiation: let the compiler deduce the actual type of the template parameter according to the actual parameter
Function templates (assuming 1 template parameter), what happens if there is a type mismatch?
We all know that C++ built-in types perform calculations and perform upward arithmetic conversions , such as int+double=double, so how does the function template handle this, or directly convert the structure into a double? Let's see:
At this point, there are two ways to deal with it: 1. The user forces the conversion by himself. 2. Use display instantiation.
User casts himself:
Add(a1,(int)d1);
2. Display instantiation: specify the actual type of the template parameter in <> after the function name
Add<int>(a1,d1);//显示实例化
2.4 Matching principle of template parameters
-
A non-template function can coexist with a function template with the same name, and the function template can also be instantiated as this non-template function
Under VS, press F11 at the break point to view and find that only Add<int>() enters the function template
- For a non-template function and a function template with the same name, if other conditions are the same, the non-template function will be called first and an instance will not be generated from the template when mobilizing. If the template can produce a function with a better match, then the template will be chosen
- Template functions do not allow automatic type conversion, but ordinary functions can do automatic type conversion
3. Class Templates
3.1 Class template definition format
template<class T1, class T2, ..., class Tn>
class 类模板名
{
// 类内成员定义
};
Note: When a function in a class template is defined outside the class, a template parameter list needs to be added
//类模板
template<class T>
class Vector
{}
//类外定义
template<class T>
Vector<T>::函数定义
3.2 Class template instantiation
//Vector类名,Vector<int>类型
Vector<int> v;
4. Non-type template parameters
namespace lh
{
// 定义一个模板类型的静态数组
template<class T, size_t N = 10>
class array
{
public:
T& operator[](size_t index) { return _array[index]; }
const T& operator[](size_t index)const { return _array[index]; }
size_t size()const { return _size; }
bool empty()const { return 0 == _size; }
private:
T _array[N];
size_t _size;
};
}
Let’s add array here. Let’s think about writing code in normal times. The array uses C++ array or C array form. Why does C++ have to create an array class?
Now that the boss has done it, it must be different from C! I don’t know if my friends usually find that the array form of C language is very loose for out-of-bounds checks!
Advantage:
In the C language, the out-of-bounds check adopts the spot check method ( pointer dereferencing ), no error is reported for out-of-bounds reading, and limited error is reported for out-of-bounds writing.
C++11, as long as the array is out of bounds, it will be found ( function call ).
5. Template specialization
5.1 Template specialization concept
Usually, templates can be used to implement some type-independent codes, but for some special types, some wrong results may be obtained, which require special handling, for example: implement a function template specially used for less than comparison
// 函数模板 -- 参数匹配
template<class T>
bool Less(T left, T right)
{
return left < right;
}
int main()
{
cout << Less(1, 2) << endl; // 可以比较,结果正确
Date d1(2022, 7, 7);
Date d2(2022, 7, 8);
cout << Less(d1, d2) << endl; // 可以比较,结果正确
Date* p1 = &d1;
Date* p2 = &d2;
cout << Less(p1, p2) << endl; // 可以比较,结果错误
return 0;
}
At this point, the template needs to be specialized. That is: on the basis of the original template class, it is a specialized implementation method for a special type . Template specialization is divided into function template specialization and class template specialization .
5.2 Function template specialization
- There must be a basic function template first
- The keyword template is followed by a pair of empty angle brackets <>
- The function name is followed by a pair of angle brackets, which specify the type to be specialized
- Function parameter table: It must be exactly the same as the basic parameter type of the template function. If it is different, the compiler may report some strange errors.
// 函数模板 -- 参数匹配
template<class T>
bool Less(T left, T right)
{
return left < right;
}
// 对Less函数模板进行特化
template<>
bool Less<Date*>(Date* left, Date* right)
{
return *left < *right;
}
void date_test()
{
cout << Less(1, 2) << endl;
Date d1(2022, 7, 7);
Date d2(2022, 7, 8);
cout << Less(d1, d2) << endl;
Date* p1 = &d1;
Date* p2 = &d2;
cout << Less(p1, p2) << endl; // 调用特化之后的版本,而不走模板生成了
}
bool Less(Date* left, Date* right)
{
return *left < *right;
}
5.3 Class template specialization
typename also tells the compiler whether this is a type or a variable!
Because static type variables can also access specified class fields, when using types, we add typename in front to distinguish them. ( Without the compiler, it is not clear whether it is a type or a variable )
6. Template separate compilation
6.1 What is separate compilation
6.2 Separate compilation of templates
Link problem: there are declarations that cannot find the definition
7. Summary
advantage:
1. The template reuses the code, saves resources, and enables faster iterative development, which is why the C++ Standard Template Library (STL) comes into being. (Repeated work is handed over to the compiler)
2. Enhanced the flexibility of the code.
shortcoming:
1. Templates can lead to code expansion problems and longer compilation times.
2. When a template compilation error occurs, the error message is very messy and it is not easy to locate the error.