Common Knowledge:
- Template code is instantiated only when it is actually used.
- Class templates support partial specialization, while function templates do not support partial specialization (similar partial specialization can be achieved through function overloading).
The template code generally goes through the following processes during compilation:
1. Syntax Checking Phase
- Check if the syntax is correct.
- Non-dependent names must be detectable.
- Dependent names are not checked.
2. Template Specialization Archiving
- Save the main definition of the template (the most general template).
- Save all partial specializations.
- Save full specializations.
3. Template Matching Process
When a template is used, template matching occurs; the matching process is as follows:
3-1 Candidate Template Collection
- Main template
- All partial specialization templates
- Full specialization templates
3-2 Attempt Template Argument Deduction for All Templates
- Based on the deduction results, keep the matching ones and eliminate the non-matching ones.
- The SFINAE (Substitution Failure Is Not An Error) rule for templates occurs at this stage.
3-3 Template Matching Ranking
- Full specialization (exact match) has the highest priority.
- Partial specializations are compared based on more specific types (narrower type ranges).
- Main template (lowest priority).
- Matching priority: Full specialization > Partial specialization > Main template.
4. Instantiation Phase
- Check dependencies.
- Instantiate class or function definitions.
- Note: Template classes are only further instantiated when their contents are used.
5. Compiler Code Generation
Finally, the compiler generates code that can be executed by the machine.
Example Code
// Template compilation process, using a template class to output information
template <typename T> struct TestTemp {
void printInfo(T t1) {
std::cout << "Primary " << std::endl;
}
};
// Partial specialization for T*
template <typename T> struct TestTemp<T*> {
void printInfo(T* t1) {
std::cout << "T* Biased specialization " << std::endl;
}
};
// Full specialization for int
template<> struct TestTemp<int> {
void printInfo(int t1) {
std::cout << "int Fully specialized " << std::endl;
}
};
inline void TestTempCompile() {
// Define a float, matching the main template
float a = 1.0;
TestTemp<float> tt1;
tt1.printInfo(a);
float* b = &a;
// TestTemp<decltype(b)> tt3;
// At compile time, all template sets are collected, the main template and partial specialization templates can match, full specialization cannot match and is eliminated, partial specialization has a higher priority than the main template, partial specialization wins
TestTemp<float*> tt3;
tt3.printInfo(b);
// At compile time, all template sets can match, full specialization has the highest priority, full specialization wins
TestTemp<int> tt2;
tt2.printInfo(10);
}
Purely for personal learning and understanding, feel free to add me on WeChat for mutual discussion and improvement. My WeChat ID is as follows:
