模版函数与模版函数的特例化

模版函数

我们知道,使用c++时必须对数据进行数据类型的定义,但是有时候这种类型的定义会显得不必要且繁琐,比如

bool bigger(const int& a,const int& b)
{
    return a>b;
}
bool bigger(const double& a,const double& b)
{
    return a>b;
}

 观察上述代码,我们要实现的是比较两个参数a和b的大小,而对于参数a参数b,由于不同的数据类型,因此我们需要重载两个数据类型的函数以满足不同的需要

那么,有没有一种办法,可以让形参的类型也可以参数化呢?这就是模版函数的作用

template<typename T>
bool bigger(const T& a,const T& b)
{
    return a>b;
}

再次观看以上代码,我们首先定义了一个模版类型参数T,这个T代表了某个类型

当我们在调用bigger函数的时候,我们可以显示指定T,当然也可以不指定,让编译器进行自动推导

如下是显示指定T的方式

bigger<int>(1,2);//显示指定T,T此时为int
bigger<double>(2.5,1);//显示指定T,T此时为double,此时尽管实参b是一个int,也会被强制转换为double

如下是隐式推断

bigger(1,2);//T此时被推断为int
bigger(1.5,2.5);//T此时被推断为double
bigger(1.5,2);//编译器推断失败,将会报错,此时必须使用显示指定T的类型进行类型转换调用

 可以看到,无论是显示指定还是隐式推断,对于同样功能的函数,此时我们只需要声明一份函数即可,而无需重复写多个函数的重载。

但需要注意的是,我们没有对函数进行重载,但并不代表编译器没有对函数进行重载。事实上,当我们在对模版函数进行调用的时候,编译器会对我们的代码进行实例化,也就是说

bigger<int>(1,2);

当我们的代码执行的这里时,编译器会为我们实例化一份对应的函数代码

bool bigger(const int& a,const int& b)
{
    return a>b;
}

同理,当我们执行以下代码时

bigger<double>(1,2);

编译器同样会为我们实例化一份这样一份代码 

bool bigger(const double& a,const double& b)
{
    return a>b;
}

模版函数的特例化

为了说明问题,我们直接看以下代码

#include<iostream>

template<typename T>
bool bigger(const T& a,const T& b)
{
    return a>b;
}


int main()
{
    std::string a="b";
    std::string b="ab";
    // bool res=bigger<double>(3.5,2);
    bool res=bigger(a,b);
    if(res)
        std::cout<<"a is bigger than b"<<std::endl;
    else
        std::cout<<"a is less than b"<<std::endl;        
    return 0;
}

我们同样定义了一份模版函数,但是我们此时定义了两个std::string类型的参数,我们想实现的是,可以比较两个string类型的参数的字符串长度

 可以看到,当我们编译运行后发现,程序的运行结果与我们的想法背道而驰了

先说为什么会出现这样的结果

首先我们知道参数a是"b",参数b是"ab",如果我们直接比较"b"和"ab"的大小,实际上比较的是这两个字符串的首地址大小,显然"b"的首地址b是大于"ab"的首地址a的

特殊情况就要特殊处理,因此出现了所谓的模版特例化

#include<iostream>

template<typename T>
bool bigger(const T& a,const T& b)
{
    return a>b;
}

template<>
bool bigger(const std::string& a,const std::string& b)
{
    std::cout<<">>>";
    return a.length()>b.length();
}

int main()
{
    std::string a="b";
    std::string b="ab";
    // bool res=bigger<double>(3.5,2);
    bool res=bigger(a,b);
    if(res)
        std::cout<<"a is bigger than b"<<std::endl;
    else
        std::cout<<"a is less than b"<<std::endl;        
    return 0;
}

再看上述代码,我们定义了在原来的模版函数的基础上,又定义了一份代码

template<>
bool bigger(const std::string& a,const std::string& b)
{
    std::cout<<">>>";
    return a.length()>b.length();
}

这个就是模版特例化的代码,针对参数类型T为std::string所声明的特例化,注意这并不是函数重载

再次编译运行

可以看到,此时代码成功调用的是特例化的代码

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值