c++模板参数自动推导

    上次,我们看了什么是模板函数,今天,我们就从这个模板函数入手,继而引出一个新的知识点-模板参数自动推导。为了介绍清楚什么是模板参数自动推导,我们先定义几个术语,通过这些术语来描述比较方便,这些术语是:模板形参,模板实参,模板函数形参,模板函数实参。

    为了表达明确,我们先来看一下图1,图1中指出了什么是模板参数,模板实参,模板函数形参,模板函数实参。

图1 术语

    就像图1所示,template<>中的参数为模板形参,get_max_type()中的参数为模板函数形参。当我们调用这个模板函数的时候,char,int为模板实参,’a’,10为模板函数实参。

    从图1的代码中,我们可以看到模板的形参和模板函数的形参在位置上,具有一定的对应关系,因此,当我们调用模板函数的时候,C++编译器会自动根据模板函数的实参来推测模板的实参,我们将这种机制成为模板参数自动推导。

    根据模板参数自动推导的规则,图1中的代码可以改写为例1,如下:

例1:根据模板参数自动推导,省略模板实参

  1. #include<iostream>  
  2. using namespace std;  
  3. template<typename T1, typename T2>  
  4. int get_max_type(T1 a, T2 b)  
  5. {  
  6.     int nMax = 0;  
  7.     if (sizeof(T1) >= sizeof(T2))  
  8.     {  
  9.         nMax = sizeof(T1);  
  10.     }  
  11.     else  
  12.     {  
  13.         nMax = sizeof(T2);  
  14.     }  
  15.   
  16.     return nMax;  
  17. }  
  18. int main(int argc, char * argv[])  
  19. {  
  20.     int nMax = get_max_type(‘a’, 10);  
  21.     cout<<”max:”<<nMax<<endl;  
  22.     return 0;  
  23. }  
#include<iostream>
using namespace std;
template<typename T1, typename T2>
int get_max_type(T1 a, T2 b)
{
    int nMax = 0;
    if (sizeof(T1) >= sizeof(T2))
    {
        nMax = sizeof(T1);
    }
    else
    {
        nMax = sizeof(T2);
    }

    return nMax;
}
int main(int argc, char * argv[])
{
    int nMax = get_max_type('a', 10);
    cout<<"max:"<<nMax<<endl;
    return 0;
}
    在例1中,因为模板形参T1和T2,在位置上,与模板函数形参a和b,具有一一对应的关系,因此,当我们调用模板函数get_max_type的时候,就可以省略模板实参char和int的输入,使调用模板函数和调用普通函数一样方便。

    虽然模板参数自动推导非常方便,但并不是所有的情况都可以使用模板参数自动推导。使用模板参数自动推导需要满足3个条件:

    1、模板的形参必须与模板函数的形参在位置上存在一一对应的关系

    2、与模板函数返回值相关的模板参数无法进行自动推导

    3、需要推导的模板参数必须是连续位于模板参数列表的尾部,中间不能有不可推导的模板参数。

    下面,我们通过几个例子来一一说明这3个条件的重要性。

例2:模板的形参与模板函数的形参位置上不存在对应关系

  1. #include<iostream>  
  2. using namespace std;  
  3. template<typename T1, typename T2>  
  4. int get_max_type(char a, int b)  
  5. {  
  6.     int nMax = 0;  
  7.     if (sizeof(T1) >= sizeof(T2))  
  8.     {  
  9.         nMax = sizeof(T1);  
  10.     }  
  11.     else  
  12.     {  
  13.         nMax = sizeof(T2);  
  14.     }  
  15.   
  16.     return nMax;  
  17. }  
  18. int main(int argc, char * argv[])  
  19. {  
  20.     int nMax = get_max_type(‘a’, 10);  
  21.     cout<<”max:”<<nMax<<endl;  
  22.     return 0;  
  23. }  
#include<iostream>
using namespace std;
template<typename T1, typename T2>
int get_max_type(char a, int b)
{
    int nMax = 0;
    if (sizeof(T1) >= sizeof(T2))
    {
        nMax = sizeof(T1);
    }
    else
    {
        nMax = sizeof(T2);
    }

    return nMax;
}
int main(int argc, char * argv[])
{
    int nMax = get_max_type('a', 10);
    cout<<"max:"<<nMax<<endl;
    return 0;
}
    在例2中,函数模板的形参T1和T2与函数模板的函数形参char和int之间,在位置上,没有任何对应关系,因此在调用这个函数模板的时候,不能进行模板参数自动推导。否则,会出现编译错误,如图2:

图2 vc2013中的编译错误

例3 与函数模板返回值相关的模板参数不能进行自动推导

  1. #include<iostream>  
  2. using namespace std;  
  3. template<typename T1, typename T2>  
  4. T1 get_max_type(char a, T2 b)  
  5. {  
  6.     int nMax = 0;  
  7.     if (sizeof(T1) >= sizeof(T2))  
  8.     {  
  9.         nMax = sizeof(T1);  
  10.     }  
  11.     else  
  12.     {  
  13.         nMax = sizeof(T2);  
  14.     }  
  15.   
  16.     return nMax;  
  17. }  
  18. int main(int argc, char * argv[])  
  19. {  
  20.     int nMax = get_max_type(‘a’, 10);  
  21.     cout<<”max:”<<nMax<<endl;  
  22.     return 0;  
  23. }  
#include<iostream>
using namespace std;
template<typename T1, typename T2>
T1 get_max_type(char a, T2 b)
{
    int nMax = 0;
    if (sizeof(T1) >= sizeof(T2))
    {
        nMax = sizeof(T1);
    }
    else
    {
        nMax = sizeof(T2);
    }

    return nMax;
}
int main(int argc, char * argv[])
{
    int nMax = get_max_type('a', 10);
    cout<<"max:"<<nMax<<endl;
    return 0;
}
    例3中,函数模板形参T2在位置上与函数模板的函数形参b具有一一对应的关系,并且位于模板参数列表的尾部,因此,可以进行自动推导;但是,模板形参T1在位置上与模板的函数形参没有任何对应关系,因此,不能进行自动推导;虽然模板形参T1和模板的函数返回值在位置上具有一一对应关系,但是,仍然不可以。具体编译效果如图3:

图3 vc2013中的编译错误

例4 欲推导的模板参数没有连续位于模板参数列表的尾部,导致中间出现了间隔,所以不能推导。

  1. #include<iostream>  
  2. using namespace std;  
  3. template<typename T1, typename T2, typename T3, typename T4>  
  4. int func(T1 v1, T3 v3, T4 v4)  
  5. {  
  6.     return 0;  
  7. }  
  8.   
  9. void main()  
  10. {  
  11.     int nTemp = 0;  
  12.     nTemp = func<, intintint>(1, 2, 3);  
  13. }  
#include<iostream>
using namespace std;
template<typename T1, typename T2, typename T3, typename T4>
int func(T1 v1, T3 v3, T4 v4)
{
    return 0;
}

void main()
{
    int nTemp = 0;
    nTemp = func<, int, int, int>(1, 2, 3);
}
    在例4中,模板参数T1虽然与模板的函数参数v1的类型存在位置上的对应关系,但是由于T2的出现,导致T1不能和T3、T4连续位于模板参数列表的尾部,所以当我们使用这个函数模板的时候,在模板参数的实参-<,int,int,int>中,T2必须填写,这样,如果省略T1,就只剩下了一个‘,’,这样就会导致编译错误;如果连‘,’也不写,即func<int,int,int>,那么,自动推导的参数就是T4,而不是T1了。

    今天,我们主要讲解了什么是模板参数自动推导以及自动推导的充要条件,希望大家能够多多实践例子中的代码,加深对模板参数自动推导的理解。








  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
模板参数推导(template argument deduction)是C++11中引入的一个新特性,它可以自动推导模板参数,避免手动指定模板参数。 在使用模板函数模板类时,通常需要手动指定模板参数,例如: ``` template<typename T> void foo(T t); int main() { foo<int>(1); // 指定模板参数为int return 0; } ``` 在上面的代码中,我们调用了模板函数`foo`,并手动指定了模板参数为int。这种方式比较繁琐,容易出错。 模板参数推导可以自动推导模板参数,避免手动指定模板参数。例如: ``` template<typename T> void foo(T t); int main() { foo(1); // 自动推导模板参数为int return 0; } ``` 在上面的代码中,我们调用了模板函数`foo`,并没有手动指定模板参数,编译器会自动推导模板参数为int。 模板参数推导可以用于函数模板和类模板的实例化过程中。它可以根据函数参数或对象成员的类型,自动推导模板参数的类型。例如: ``` template<typename T, int N> class Array { public: T data[N]; }; int main() { Array arr{1, 2, 3}; // 自动推导模板参数为int和3 return 0; } ``` 在上面的代码中,我们定义了一个类模板`Array`,它有两个模板参数,一个是类型参数T,一个是整型参数N。在实例化`Array`对象时,我们只传入了一个参数{1, 2, 3},编译器会自动推导模板参数为int和3。 需要注意的是,模板参数推导只能用于函数模板和类模板的实例化过程中,不能用于模板定义中。在模板定义中,必须手动指定模板参数
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值