对于函数模板,编译器利用调用中的函数实参来确定其函数模板,从函数实参来确定模板实参的过程就被叫做是模板实参推导。

比如:

 1 #include<iostream>
 2 #include<string>
 3 using namespace std;
 4
 5 template <class T>
 6 int compare(const T &v1, const T &v2) {
 7     if (v1 > v2) {
 8         cout << "bigger" <<endl;
 9         return 0;
10     }
11     else {
12         cout << "small" <<endl;
13         return 1;
14     }
15 }
16
17 template <class T>
18 int compare1(T v1,T v2) {
19     if (v1 > v2) {
20         cout << "compare1::bigger" <<endl;
21         return 0;
22     }
23     else {
24         cout << "compare1::small" <<endl;
25         return 1;
26     }
27 }
28
29 int main() {
30     compare(0, 1);                // 调用compare(const int&, const int&)
31     compare(3.14, 2.7);           // 调用compare(const float&, const float&)
32     compare(2, 2.7);              // error33
34     system("pause");
35     return 0;
36 }

在模板实参推导过程中,编译器使用函数调用中的实参类型来寻找模板实参,用这些模板实参生成的函数版本与给定的函数调用最为匹配.

一、模板推导规则

模板实参推导还有以下的规则:

1.如果某个函数的多个形参的类型是同一个模板类型形参,推断出来的函数的这些实参类型要完全匹配

就像上面例子上的compare(2, 2.7);一样,必须完成匹配。

2.如果模板函数的形参是非引用类型,忽略const。例:

    string s1("a");const string s2("ab");compare1(s1, s2);   // 调用compare1(string, string)

3.形参如果是const 引用或者指针,实参可以使非const引用或者指针,编译器会自动转换到const。例:

    string s1("a");const string s2("ab");compare(s1, s2);    // 调用compare(const string&, const string&)

4.非引用类型模板形参可以将数组或函数类型的实参转换成数组指针或函数指针。例:

    int a[10], b[11];compare1(a, b);   // 调用compare1(int*, int*)

5.引用类型模板形参不能将将数组或函数类型的实参转换成数组指针或函数指针,参数推导将出错。例:

    int a[10], b[11];compare(a, b);   // error

6.可以根据函数指针推断模板实参

7.模板实参推断顺序是从函数返回值开始,从左至右逐一推导。例如:

template <typename T1, typename T2, typename T3>
T1 sum(T1 t1, T2 t2) {return t1 + t2;
}auto x = sum<int, int, int>(1, 2); 

但需要注意的是:匹配是从左往右进行的,只有尾部(最右)参数的显示模板实参才可以省略,而且前提是他们可以从函数参数推断出来。

    int i = 1;auto x = sum<int, int>(1, i);  // VS2012上有错误,尚不知为何

二、实参类型不同的模板推导

在上面的1中,如果某个函数的多个形参的类型是同一个模板类型形参,推断出来的函数的这些实参类型要完全匹配,否则则要出错。

但是,我们可以使用多个类型的参数来实现推导。例:

 1 #include<iostream>
 2 #include<string>
 3 using namespace std;
 4
 5 template <typename T, typename B>
 6 int compare(const T &v1, const B &v2) {
 7     if (v1 > v2) {
 8         cout << "bigger" <<endl;
 9         return 0;
10     }
11     else {
12         cout << "small" <<endl;
13         return 1;
14     }
15 }
16
17 int main() {
18     long l = 655555;
19     compare(l, 2);        // 调用(const long&, const int&)
20
21     system("pause");
22     return 0;
23 }

此外,我们还可以显示的指定实参的类型,例如:

compare<long, int>(100000, 2);

三、确定模板的返回类型

在1.7的情况中,我们虽然可以确定模板的返回类型,但是开销非常大,于是C++11推出了另外一种用来解决模板返回类型的方法:decltype

template<typename T>
auto foo(T x) -> decltype(*x)   // 指定返回x的引用类型
{return *x;
}int a[3] = {1,2,3};auto &z = foo(a);  // 返回int&

转载于:https://www.cnblogs.com/hustcser/p/4040958.html

[014]模板-模板实参推导相关推荐

  1. 模板实参推导 xx_cast的实现

    首先,类模板必须被显式特化.当然了,可以通过一个辅助函数,通过参数类型,返回特化的类模板,来间接处理. 这个技术被广泛应用在ptr_fun, make_pair, mem_fun, back_inse ...

  2. C++17尝鲜:类模板中的模板参数自动推导

    目录 模板参数自动推导 示例 自定义类模板中的应用 Automatic deduction guides(自动推断向导) 模板参数自动推导 在C++17之前,类模板构造器的模板参数是不能像函数模板的模 ...

  3. C++基础——对函数模板的类型推导的补充

    这里忽然想到一个问题: template<typename T> void foo() {T x = T(); }template<typename T> void foo2( ...

  4. C++模板——模板特化、分离编译

    这里写目录标题 一.泛型编程与模板 二.函数模板 1.概念 2.原理 3.函数模板的实例化 3. 模板实现复数类的加法 4.模板参数的匹配原则 三.类模板 1.定义格式 用类模板实现顺序表 2.非类型 ...

  5. PHP资源模板——模板终结者

    转自:http://club.phpe.net/index.php?act=ST&f=15&t=12080 1 PHP资源模板--模板终结者   2 导演:axgle   3 主演:小 ...

  6. 什么是模板模板参数?

    模板模板参数名字比较绕嘴,其意思就是让模板参数本身成为模板. 现在有一个需求,创建一个TyClass的类模板,这个类模板,有一个成员变量myc,这个成员变量是一个容器(可能是一个vector或者lis ...

  7. C++基础——使用字符串作为函数模板的实参

    在<C++基础--一些细节.常犯错误的汇总>一文的细节3中,我们看到, const char* s = "hello"; s的类型是const char*," ...

  8. php smarty继承,PHP Smarty 模板 模板继承 {extends}

    {extends} 模板继承中,你可以在子模板内使用{extends}标签来扩展父模板. 1.{extends}必须放在模板的第一行. 2.如果子模板要用{extends}来扩展父模板,那么它只能有 ...

  9. 【开发环境】010 Editor 工具 ( 工具下载 | 二进制文件分析模板模板安装 | 快捷键查看与设置 )

    文章目录 一.010 Editor 工具下载 二.010 Editor 安装二进制文件分析模板 三.010 Editor 快捷键查看与设置 一.010 Editor 工具下载 下载地址 : https ...

最新文章

  1. mysql cluster 视频_mysql cluster 部署实战
  2. studio 3t 在ubuntu中使用_在ubuntu中使用ufw配置防火墙
  3. 晚上我们一起去白码会所玩啊!
  4. Windows下svn服务器安装
  5. python编程软件哪个好-python IDE有哪些?哪个好用?
  6. 图神经网络(二)--GNNs
  7. 模式识别与机器学习(一):概率论、决策论、信息论
  8. 代码片段---重定向
  9. FlashFXP绿色版下载与怎么用
  10. excel中的联系方式导入手机电话簿
  11. android 汉字拼音排序,Android实现中文按拼音排序方法
  12. 网页做服务器的监控界面,服务器监控页面
  13. 智能衣橱控制系统的设计
  14. CEO年薪过亿,谁说了算?
  15. R语言 | 关联规则
  16. Cantor表 [cantor]
  17. __name__的用法
  18. (Nginx出现403 forbidden)nginx权限问题failed(13:Permission denied)
  19. html中文本重复,在网页中去除文本列表中重复行与计算重复次数的代码原理
  20. 高效能管理之要事第一 时间管理表格

热门文章

  1. 转换预定义的字符为html实体,php把一些预定义的 HTML 实体转换为字符。
  2. 删除顺序表中重复元素,并按照原序输出
  3. 163 邮件 服务器 ssl,为什么用163的smtp服务时要关闭TLS才能发送邮件?
  4. 计算机课计划,计算机教学计划汇总
  5. vep文件如何转换mp4_如何将m4v视频格式快速转换成mp4视频呢
  6. python replace替换多个字符_关于python:使用string.replace(x,y)替换所有
  7. 北航 计算机学院 2011级学生会,北航学生会主席在2011级新生开学典礼发言稿.doc...
  8. 学mysql需要学python吗_python 学习 第六篇 mysql
  9. nginx php.ini配置_Nginx下修改php.ini后重新加载配置文件命令
  10. python os path isfile_Python path.isfile方法代码示例