文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

C++学习之函数模板的使用详解

2023-03-02 20:50

关注

C++函数模板

template<typename T>
void Swap(T &a ,T &b)
{
    T temp;
    temp = a;
    a = b;
    b = temp;
}

在使用模板函数时,编译器根据实际的类型生成相应的函数定义。

重载的模板

并非所有的类型都使用相同的算法,可以像重载常规函数那样重载模板函数定义。

template<typename T>
void Swap(T &a ,T &b); //#1

template<typename T>
void Swap(T *a ,T *b,int n);//#2 最后一个参数是具体类型

int main()
{
    int i =10,j=20;
    Swap(i,j);//使用#1
    
    const int Lim = 8;
    int d1[Lim]={0,1,2,3,4,5,6,7};
    int d2[Lim]={7,6,5,4,3,2,1,0};
    Swap(d1,d2,Lim);//使用#2
}
template<typename T>
void Swap(T &a ,T &b)
{
    T temp;
    temp = a;
    a = b;
    b = temp;
}

template<typename T>
void Swap(T *a ,T *b,int n)
{
    T temp;
    for(int i=0;i<n;i++)
    {
        temp =a[i];
        a[i]=b[i];
        b[i]=temp;
    }
}

模板局限性

某些时候,类型T的相应操作只适用于数组,如果T为结构体则模板函数便不成立

同样,如if(a>b),如果T为结构,则>便不成立

解决方案:

显示具体化

当编译器找到与函数调用匹配的具体化定义时,将使用该定义,不再寻找模板。

void Swap(job& ,job&);

template <typename T>
void Swap(T&,T&);

template<> void Swap<job>(job& ,job&);//显示具体化
//Swap<job>中<job>是可选的,因为函数的参数类型表明,这是job的一个具体化,所以也可以这样写:
template<> void Swap(job& ,job&);

实例化和具体化

注意:函数模板并不会生成函数定义,他只是生成一个用于生成函数定义的方案,编译器使用模板为特定的类型生成函数定义时,得到的是模板实例。

template<typename T>
void Swap(T &a ,T &b);

int a =10,b=20;
Swap(a,b);//因为提供了int类型的参数,所以自动生成了int类型的模板实例。这样是==隐式实例化==
//也可以直接命令编译器创建特定的实例
//显示实例化
template void Swap<int>(int &,int &);//使用Swap()模板生成int类型的函数定义

//显示具体化
template<> void Swap<int>(int& ,int&);
template<> void Swap(int& ,int&);
//区别在于:具体化是不使用Swap()模板函数生成函数定义,而是使用专门为int类型显示定义的函数定义
//简单的理解,具体化是对函数的声明,而实例化是对模板函数的使用
template<typename T>
T Add(T a,T b)
{
    return a+b;
}

int m=6;
double x=10.5;
Add<double>(x,m); //与Add(x,m)不匹配,因为一个是int一个是double
				  //通过Add<double>实例化,可强制将m转为double

//但是同样的对Swap便不能成功,因为Swap中使用的是引用类型
Swap<double>(m,x);//double& 不能指向int
//使用案例
template <typename T>
void Swap(T &,T &);

template<> void Swap<job>(job&,job&);//具体化
int mian()
{
    template void Swap<char>(char& ,char&);
    
    short a,b;
    Swap(a,b);//隐式实例化
    
    job n,m;
    Swap(n,m);//显示具体化
    
    char g,h;
    Swap(g,h);//显示实例化
}

模板函数类型的确定

template<class T1,class T2>
void fun(T1 x,T2 y)
{
    ?type? s=x+y; //因为是模板函数,此时?type?类型不确定
}

C++11增加decltype关键字

template<class T1,class T2>
void fun(T1 x,T2 y)
{
    decltype(x+y) s=x+y; //s类型与x+y的类型一致
}

使用decltype(expression) var 的步骤:

1.如果expression没有用括号括起来,则var与expression类型相同,包括const等限定符

double x =5.5;
double& z =x;
const double* pd;
decltype(x) w; //w为double类型
decltype(z) u; //u为double& 类型
decltype(pd) v; //v为const double* 类型

2.如果expression是一个函数调用,则var与返回值类型相同。并不会实际调用函数,编译器通过查看原型来确定返回值类型

3.如果expression是一个左值,则var为指向其类型的引用。常见的情况如下:

double x = 4.5;
decltype((x)) r = x;//r是double&类型
decltype(x) r = x;//r是double类型

//括号不会改变expression的值和左值性
//可理解为加括号仅仅是decltype声明引用的一种方式

4.如果前3条都不满足,则var与expression类型相同

int j=3;
int &k=j;
int &n=j;

decltype(j+6) x; //x是int
decltype(k+n) y;//y是int ,虽然k和n是引用,但是k+n不是引用是2个int的和

如果多次声明,可以结合typedefdecltype

typedef decltype(x+y) xytype;
xytype z = x+y;
xytype arr[10];

但是某些需定义返回值类型的函数模板任然不能得到解决,如:

template<class T1,class T2>
?type? fun(T1 x,T2 y) //此时无法确定类型
{
    return x+y;
}

C++新增语法auto h(int x,float y) -> double,这称为后置返回类型,auto是一个占位符

template<class T1,class T2>
auto fun(T1 x,T2 y)->decltype(x+y) //后置类型使用decltype
{
    return x+y;
}

到此这篇关于C++学习之函数模板的使用详解的文章就介绍到这了,更多相关C++函数模板内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     801人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     348人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     311人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     432人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     220人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯