模板编程——函数模板

目录

模板概述

重要概念

示例代码

sort函数模板

compare函数模板


模板概述

模板的意义是可以对类型进行参数化

相关关键字:templatetypenameclass

template用于定义模板,typenameclass用于定义模板类型参数

重要概念

1、函数模板

函数模板是一种通用的函数定义

接受不同类型参数进行调用,以实现对多种类型的操作的复用

2、模板类型参数

模板类型参数是在函数模板或类模板中使用的占位符类型

允许在模板定义中使用未知类型,并在实例化时通过具体类型进行替换

使用关键字typename或class定义模板类型参数

3、模板非类型参数

模板非类型参数是在函数模板或类模板中使用的常量表达式

4、模板特例化(专用化)

模板特例化是一种为特定的类型参数提供特定实现或处理的机制

允许在模板的基础上为特定的类型或值提供自定义的行为

特例化分为全特例化(完全特例化)和偏特例化(部分特例化)两种类型

------------------------------------------------------------

5、模板函数

模板函数是使用模板定义的函数,允许在不同的参数类型上进行通用操作

编译器会编译模板函数,但不会编译函数模板

因为模板类型参数不明确,所以函数模板无法进行编译

6、模板实例化

模板实例化发生在函数调用点

模板实例化是在使用模板时,编译器根据特定的类型参数或值参数生成实际代码的过程

7、模板实参推演

模板实参推演是指编译器根据函数调用或对象创建上下文中提供的实际参数来确定模板的实际类型参数

在函数模板实例化时,如果没有显式指定模板参数类型,编译器会根据函数调用传递的实参类型来推导模板参数类型

示例代码

sort函数模板

// sort函数模板

#include
using namespace std;

template
// T是模板类型参数,SIZE是模板非类型参数
void sort(T * arr) // 冒泡排序
{
    for(int i = 0; i < SIZE - 1; i ++)
    {
        for(int j = 0; j + 1 < SIZE - i; j ++)
        {
            if(arr[j] > arr[j + 1])
            {
                int temp = arr[j];
                arr[j] = arr[j + 1];
                arr[j + 1] = temp;
            }
        }
    }
}

int main()
{
    int arr[] = {1,2,10,9,3,5,6,4,8,7};
    const int size = sizeof(arr) / sizeof(arr[0]);
    // 注意!此处必须写成const int size
    // 因为模板非类型参数必须是常量

    cout << "排序前:" << endl;
    for(const int & i : arr)  cout << i << " ";  cout << endl;
    sort(arr);
    cout << "排序后:" << endl;
    for(const int & i : arr)  cout << i << " ";  cout << endl;
    
    return 0;
}

/*
排序前:
1 2 10 9 3 5 6 4 8 7 
排序后:
1 2 3 4 5 6 7 8 9 10 
*/

compare函数模板

// compare函数模板

#include
#include
using namespace std;


// 定义compare函数模板
template
// T是模板类型参数
// 是模板参数列表,也可写成template
bool compare(T a, T b) // compare是函数模板名
{
    cout << "compare function template is working!" << endl;
    return a > b;
}
// 注意!因为T类型不明确,所以函数模板无法进行编译

// 模板特例化(专用化)
// 对于compare函数模板,提供const char *类型的特例化版本
template<>
bool compare(const char * a, const char * b)
{
    cout << "special compare is working!" << endl;
    return strcmp(a, b) > 0;
}


// 普通函数(非模板函数)
bool compare(const char * a, const char * b)
{
    cout << "ordinary function compare() is working!" << endl;
    return strcmp(a, b) > 0;
}


int main()
{
    // 示例1
    compare(10, 20); // 函数调用点
    // 函数模板名compare + 参数列表 = 函数名compare
    // 在此函数调用点,编译器使用用户指定类型int从compare函数模板实例化一份如下模板函数:
    /*
        // 模板函数
        // 编译器会编译模板函数
        bool compare(int a, int b)  { return a > b; }
    */

    // 示例2
    compare(10.5, 20.5); // 函数调用点
    /*
        // 模板函数
        // 编译器会编译模板函数
        bool compare(double a, double b)  { return a > b; }
    */
    
    // 示例3
    compare(10, 20);
    // 此处只指明函数模板名compare,并未指定参数列表,此时会进行函数模板实参推演

    // 示例4
    compare(10, 20.5);
    // 注意!compare(10, 20.5)无法进行函数模板实参推演
    // 因为函数模板的模板参数列表中只有一种类型,而此处涉及int和double两种类型
    cout << "--------------------------------------------------" << endl;

    // 示例5
    compare("aaa", "bbb");
    // 优先视compare为函数名,所以此处调用普通函数
    // 注意!如果没有编写普通函数compare(),也没有编写const char *类型的特例化版本
    // 那么会进行函数模板实参推演,推导出T为const char *
    // 那么a > b比较的是地址大小,并不是字典序大小(strcmp(a, b) > 0比较字典序大小)
    // 显然,这不符合逻辑,所以需要编写普通函数compare()或const char *类型的特例化版本
    cout << "--------------------------------------------------" << endl;

    // 示例6
    compare("aaa", "bbb");
    // 此处调用const char *类型的特例化版本
    cout << "--------------------------------------------------" << endl;

    return 0;
}

/*
compare function template is working!
compare function template is working!
compare function template is working!
compare function template is working!
--------------------------------------------------
ordinary function compare() is working!
--------------------------------------------------
special compare is working!
--------------------------------------------------
*/

你可能感兴趣的:(C++,c++,函数,模板)