[C++]57_Deep Understanding Function Template

Keywords: C++ Programming

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!

Posted by apenster on Fri, 03 May 2019 19:10:38 -0700