Function template
-
Deep Understanding of Function Templates
- The compiler generates different functions from function templates by specific types
-
The compiler compiles the function template twice
- Compile the template code itself (syntax checking, etc.)
- Compile the code after parameter substitution (syntax checking, etc.)
-
Matters needing attention
-
Function templates themselves do not allow implicit type conversion
- When deriving types automatically, strict matching is necessary.
- Implicit type conversion is possible when the display type is specified
-
Programming Experiments: The Essence of Function Templates
#include <iostream> using namespace std; class Test { public: Test() { } }; template < typename T > void Swap(T& a, T& b) { T c = a; a = b; b = c; } typedef void(FuncI)(int&, int &); typedef void(FuncD)(double&, double &); typedef void(FuncT)(Test&, Test &); int main() { FuncI* pi = Swap; // Compiler automatically deduces T to int FuncD* pd = Swap; // Compiler automatically deduces T to double FuncT* pt = Swap; // Compiler automatically deduces T to Test cout << "pi = " << reinterpret_cast<void*>(pi) << endl; cout << "pd = " << reinterpret_cast<void*>(pd) << endl; cout << "pt = " << reinterpret_cast<void*>(pt) << endl; return 0; }
Output: pi = 0x80487e4 pd = 0x8048806 pt = 0x8048828 What does the compiler do? FuncI* pi = Swap; ==> Compiler automatic type derivation==> generates corresponding Swap function==> grammar check validity and assigns Swap address to pi
Two Compilations of Function Templates by the Compiler
First time: Compile and check the template code itself
#include <iostream> using namespace std; template < typename T > void Swap(T& a, T& b) { T c = a // Watch out here! Deliberately Made Grammatical Errors a = b; b = c; } int main() { return 0; }
Output: g++] test.cpp: In function 'void Swap(T&, T&)': test.cpp:9: error: expected ',' or ';' before 'a'
Second time: Compile and check the code after parameter replacement
#include <iostream> using namespace std; class Test { private: Test(const Test& obj); // Watch out here! Declare the copy constructor as private public: Test() { } }; template < typename T > void Swap(T& a, T& b) { T c = a; a = b; b = c; } typedef void(FuncT)(Test&, Test &); int main() { FuncT* pt = Swap; // Compiler automatically deduces T to Test return 0; }
Output: [g++] test.cpp: In function 'void Swap(T&, T&) [with T = Test]': test.cpp:27: instantiated from here test.cpp:8: error: 'Test::Test(const Test&)' is private test.cpp:18: error: within this context Analysis: FuncT* pt = Swap; ==> Compiler automatic type inference, T is Test type==> Generate corresponding Swap function==> Grammar check copy constructor is private, give error hints
Multi-parameter function template
- Function templates can define any number of different type parameters
template < typename T1, typename T2, typename T3 > T1 Add(T2 a, T3 b) { return static_cast<T1>(a + b); }
==>
int r = Add<int, float, double>(0.5, 0.8);
-
For multi-parameter function templates
- Unable to automatically deduce return value type
- You can specify parameter types from left to right
// T1 = int, T2 = double, T3 = double int r1 = Add<int>(0.5, 0.8); // T1 = double, T2 = double, T3 = float double r2 = Add<double, float>(0.5, 0.8); // T1 = float, T2 = float, T3 = float float r3 = Add<float, float, float>(0.5, 0.8);
Regarding the return value parameter as the first type parameter in Engineering
Programming experiment: multi-parameter function template
#include <iostream> using namespace std; template < typename T1, typename T2, typename T3 > T1 Add(T2 a, T3 b) { return static_cast<T1>(a + b); } int main() { // T1 = int, T2 = double, T3 = double int r1 = Add<int>(0.5, 0.8); // T1 = double, T2 = double, T3 = float double r2 = Add<double, float>(0.5, 0.8); // T1 = float, T2 = float, T3 = float float r3 = Add<float, float, float>(0.5, 0.8); cout << "r1 = " << r1 << endl; cout << "r2 = " << r2 << endl; cout << "r3 = " << r3 << endl; return 0; }
Output: r1 = 1 r2 = 1.3 r3 = 1.3
Interesting questions:
What happens when a function overload meets a function template?
Overload function template
-
Function templates can be overloaded like normal functions
- C++ Compiler Priorities Common Functions
- If function templates can produce better matches, then select templates
- The compiler can be limited to match only templates by an empty template argument list
int r1 = Max(1, 2); double r2 = Max<>(0.5, 0.8);
Example analysis: overloaded function template
#include <iostream> using namespace std; template < typename T > T Max(T a, T b) { cout << "T Max(T a, T b)" << endl; return a > b ? a : b; } int Max(int a, int b) { cout << "int Max(int a, int b)" << endl; return a > b ? a : b; } template < typename T > T Max(T a, T b, T c) { cout << "T Max(T a, T b, T c)" << endl; return Max(Max(a, b), c); } int main() { int a = 1; int b = 2; cout << Max(a, b) << endl; // Common function Max(int, int) cout << Max<>(a, b) << endl; // Function template Max < int > (int, int) cout << Max(3.0, 4.0) << endl; // Function template Max < double > (double, double) cout << Max(5.0, 6.0, 7.0) << endl; // Function template Max < double > (double, double, double) cout << Max('a', 100) << endl; // Common function Max(int, int) return 0; }
Output: int Max(int a, int b) 2 T Max(T a, T b) 2 T Max(T a, T b) 4 T Max(T a, T b, T c) T Max(T a, T b) T Max(T a, T b) 7 int Max(int a, int b) 100 Tips: Max('a', 100) Ordinary function is called Implicit type conversion is not allowed in function template itself. Implicit type conversion is performed after ordinary functions are matched.
Summary
- Function templates generate different functions by specific types
- Function templates can define any number of different type parameters
- The return value type in the function template must display the specified value
- Function templates can be overloaded like normal functions
The above content refers to Ditai Software College series courses, please protect the original!