设为首页 加入收藏

TOP

1.2.3 模板参数自动推导
2013-10-07 16:31:08 来源: 作者: 【 】 浏览:255
Tags:1.2.3 模板 参数 自动 推导

1.2.3 模板参数自动推导

如果仔细观察例1.4中的两次对max_element的调用,就会发现模板参数值与函数调用给出的实参的类型是相关的。

比如第一次调用时给出的模板参数T=int,而调用时给出的实参l的类型是int[],即一个整数数组指针,与const int*等价。同样,第二次调用时模板参数T=char,而给出的实参cl类型也是char[]。对比max_element模板的函数参数列表中形参l的类型为T const *,无需显式指定,完全可以根据调用时的实参类型推导出模板参数值。

实际上,在C++(www.cppentry.com)语言中实现了这一自动推导模板参数值的功能。凡是可以推导出的模板参数“值”,就无需在模板实参列表中写明。因此,例1.4中main函数的两次max_element调用,可以简写成以下形式:

  1. std::cout << max_element(l, 8) << std::endl;  
  2. std::cout << max_element(cl, 6) << std::endl

从而使得模板调用看起来与普通函数调用无异,也使代码看起来更整洁。

利用模板参数推导时需要注意以下几点:

编译器只根据函数调用时给出的实参列表来推导模板参数值,与函数参数类型无关的模板参数其值无法推导。

与函数返回值相关的模板参数其值也无法推导。

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

例1.5是一个简单的程序。

例1.5

  1. #include <iostream> 
  2.  
  3. template<typename T0,  
  4.          typename T1,  
  5.          typename T2,  
  6.          typename T3,  
  7.          typename T4> 
  8. T2 func(T1 v1, T3 v3, T4 v4);  
  9.  
  10. int main() {  
  11.  
  12.     double sv2;  
  13.  
  14.     using namespace std;  
  15.     sv2 = func<double, int, int>(1, 2, 3);  
  16.     cout << "\tsv2: " << sv2 << endl;  
  17.  
  18.     sv2 = func<double, int, int>(1, 2, 3);  
  19.     cout << "\tsv2: " << sv2 << endl;  
  20.  
  21.     sv2 = func<double, int, int>(1, 0.1, 0.1);  
  22.     cout << "\tsv2: " << sv2 << endl;  
  23.  
  24.     sv2 = func<int, double, double>(0.1, 0.1, 0.1);  
  25.     cout << "\tsv2: " << sv2 << endl;  
  26. }  
  27.  
  28. template<typename T0,  
  29.          typename T1,  
  30.          typename T2,  
  31.          typename T3,  
  32.          typename T4> 
  33. T2 func(T1 v1, T3 v3, T4 v4)  
  34. {  
  35.     T0 static sv0 = T0(0);  
  36.     T2 static sv2 = T2(0);  
  37.  
  38.     std::cout << "\tv1: " << v1 
  39.               << "\tv3: " << v3 
  40.               << "\tv4: " << v4 
  41.               << "\t|| sv0: " << sv0;  
  42.     T2 v2 = sv2;  
  43.  
  44.     sv0 -1;  
  45.     sv2 -1;  
  46.  
  47.     return v2;  

在这个简单的程序中首先是一个函数模板func的声明。是的,模板与普通函数及类一样,可以先声明后实现。编译器在处理该模板声明时,已知这个模板接受5个模板参数,依次为T0~T4,其中用于声明函数参数类型的模板参数为T1、T3和T4。T2用于声明函数的返回值类型,T0则与函数参数类型以及返回值类型都不相关。编译器在遇到main函数中对func函数模板的调用时,根本无法从实参类型推导出T0的值,所以T0的值必须在模板实参列表中给定。至于T2,虽然与函数返回值类型相关,粗略一想,似乎可以在某些情况下反推出T2的值,例如:

  1. double d = func<...>(...); 

可否认为T2的值就应该是一个double型呢?其实不然。由于C++(www.cppentry.com)中存在内建自动类型转换机制,double型变量不仅可以接受其他double型变量或常量的赋值,也可以接受诸如int型、char型等多种类型变量常量的值,更何况还有用户自定义的类型转换。如果不在模板参数列表中显式给定函数返回值类型,则以上代码就会产生歧义。况且有的时候函数返回值有可能被忽略。因此函数返回值类型不能根据上下文推断,也就无法自动推导出与函数返回值相关的模板参数值,所以T2的值也必须在调用时给定。又因为T2必须给定,而模板形参与实参之间只能通过位置相关联,因此虽然T1的值可由函数实参类型推导出,也必须在模板实参列表中给出。很遗憾,C++(www.cppentry.com)中并不能支持类似以下的方式来跳过对T1赋值:

  1. sv0 = func<double, , int>(1, 2, 3); // 语法错误! 

所以,例1.5中调用func时,模板实参列表中只可将T3及T4省略,而T0、T1及T2不能省略。
 

】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇C++模板”>>”编译问题与词.. 下一篇1.2.4 模板参数默认值

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容: