个人技术分享

C++ 函数模板

一、函数模板的定义

函数模板是一种通用的函数定义,可以在不同数据类型下进行重复使用,从而提高代码的复用性和灵活性。通过函数模板,可以编写与数据类型无关的通用函数,使得同一套代码可以适用于不同的数据类型。(总结说就是将虚拟类型转换为具体类型)。

函数模板实例化得到的函数是模板函数。

二、函数模板操作

代码示例:

// 请编写一个函数模板 maxElement,该函数接受一个数组和数组的大小作为参数,并返回数组中的最大元素。 注意,数组可以是包含任意类型元素的泛型数组。请确保你的函数模板能够处理不同类型的数组,并找出最大值

#include <iostream>
#include <string>
using namespace std;

template <typename T>//模板类型参数声明
// T arrayNum(T arr[],int size)//常规套路
// {
//     T temp = arr[0];
//     for(int i = 1;i < size-1;i++)
//     {
//         if(temp < arr[i])
//         {
//             temp = arr[i];
//         }
//     }
//     return temp;
// }
T arrayNum(T arr[],int size)//通用模板函数,T:返回值类型,也用来声明模板类型参数
{
    T temp = 0;
    for(int i = 0;i <size - 1;i++)//复习下冒泡排序
    {
        for(int j = i;j < size-1-i;j++)
        {
            if(arr[j] > arr[j+1])
            {
                temp = arr[j];
                arr[j] = arr[j+1];
                arr[j+1] = temp;
            }
        }
    }
    return arr[size-1];
}
int main()
{
    int arr1[] = {1,5,3,9,2};
    double arr2[] = {1.2,5.2,6.6,0.5};
    int max1 = arrayNum(arr1,5);//隐式实例化,通过参数类型推导
    double max2 = arrayNum<double>(arr2,4);//显示实例化,编译器通过<>中的数据类型推到
    cout<<"最大整数元素:"<<max1<<endl;
    cout<<"最大浮点数元素:"<<max2<<endl;
    return 0;
}

 运行结果:

最大整数元素:9
最大浮点数元素:6.6

三、函数模板和普通函数的区别

1、相对于普通函数,模板函数多了模板声明templat<typename T>。

2、相对于函数重载,函数模板更方便,可以根据类型参数自动生成对应的函数代码。提高代码的灵活性,而函数重载需要手动编写多个函数来处理不同的参数类型。

四、调用规则

1、同时存在优先调用普通函数(效率更高)。

2、空模板强制调用函数模板。

3、函数模板重载(根据参数不同进行重载)。

代码示例:

#include <iostream>
using namespace std;
template<typename T>

void print(T a,T b){
    cout<<"调用函数模板"<<endl;
}
template<typename T>
void print(T a,T b,T c){
    cout<<"调用函数模板重载"<<endl;
}
void print(int a,int b){
    cout<<"调用普通函数"<<endl;
}
int main()
{
    int a = 1;
    int b = 2;
    int c = 3;
    print(a,b);
    print(3.4,3.5);
    //空模板参数,会强调用函数模板
    print<>(a,b);
    print(3.5,3.6,3.7);
    return 0;
}

运行结果:

调用普通函数
调用函数模板
调用函数模板
调用函数模板重载

五、函数特化

操作步骤:

1、前提:要有一个基础的函数模板

2、关键字template后接一对<>

注:<>内的数据类型用于指定的数据类型

例如:

template<>

int templateSum<int>(int a,int b);

代码示例:

// 请编写一个函数模板 maximum,用于比较两个数的大小并返回较大的数。

// 然后针对整型数据类型和浮点型数据类型分别进行函数模板特化。

// 请编写一个主函数进行测试,分别传入整型和浮点型数据进行比较,并输出结果。

#include <iostream>
#include <string>
using namespace std;

template<typename T>
T maxNum(T a,T b){
    if(a > b)
    {
        return a;
    }
    else
    {
        return b;
    }
}
template<>
int maxNum<int>(int a,int b)
{
    cout<<"使用(int)函数模板特化:";
    if(a > b)
    {
        return a;
    }
    else
    {
        return b;
    }
}


template<>
string maxNum<string>(string a,string b)//比较字符串长度
{
    cout<<"使用(string)函数模板特化:";
    if(a > b)
    {
        return a;
    }
    else
    {
        return b;
    }
}

template<>
const char *maxNum<const char *>(const char *a,const char *b)
{
    cout<<"使用(const char*)函数模板特化:";
    if(a > b)
    {
        return a;
    }
    else
    {
        return b;
    }
}
int main()
{
    double num1 = maxNum(15.6,175.5);
    cout<<"num1 = "<<num1<<endl;
    int num2 = maxNum(6,50);
    cout<<"num2 = "<<num2<<endl;
    string str1 = "Hello";
    string str2 = "World";
    string num3 = maxNum(str1,str2);
    cout<<"num3 = "<<num3<<endl;
    string num4 = maxNum("Hello","World");
    cout<<"num4 = "<<num4<<endl;
    return 0;
}

运行结果:

num1 = 175.5
使用(int)函数模板特化:num2 = 50
使用(string)函数模板特化:num3 = World
使用(const char*)函数模板特化:num4 = World

函数特化的优势:

函数特化版本相对于通用版本的优势在于性能更高和资源利用更有效。由于函数特化版本是针对特定的输入类型或参数类型进行优化的,因此可以避免通用版本中的类型检查和转换操作,从而提高运行速度。另外,函数特化版本还可以更好地利用硬件特性,如SIMD指令集等,进一步提升性能。