模板实参推断

一、模板函数显示实参

情况1:

template <typename T1, typename T2, typename T3>
T1 sum(T2 a, T3 b)
{return a + b;
}

分析:调用的时候就需要指定T1的类型,如:sum<float>(1, 2); 于是sum函数的返回类型为float。

情况2:

template <typename T1, typename T2, typename T3> //糟糕的设计,用户必须指定所有的三个模板参数
T3 sum(T1 a, T2 b)
{return a + b;
}

分析:对于sum<float>(1, 2); 现在这个调用里指定T1类型为float,但是实际传进来的是1(int类型),会进行隐式类型转换,将1转换为float. T2的类型也可以根据sum(1,2)调用的第二个实参推断出来,这里是可能会是int. 那么T3是什么类型呢?显然这里编译器无法推断T3的类型,需要在调用时指定才能推断:

1.   sum<int, int, int>(1, 2); 这样T3就推断出来是int。

2. 在指定显示模板实参时指定的类型是和模板参数匹配的,顺序是一一对应的,如:

•  使用 sum<int>(1, 2); 对上面的第一个模板进行调用,那么T1对应int,T2和T3则通过推断得出。

•  使用 sum<int>(1, 2); 对上面的第二个模板进行调用,那么T1对应的类型是int,T2可以根据实际穿进去的参数进行推断,这里2为int,那么T2类型就是int,那么编译器就无法知道T3的实际类型了。

 二、完美转发

template<class T>
void wrapper(T&& arg)
{// arg 始终是左值foo(std::forward<T>(arg)); // 转发为左值或右值,依赖于 T
}  分析:1. 若对 wrapper() 的调用传递右值string ,则推导 T 为 std::string(非string& 或string&& ,且 std::forward 确保将右值引用传递给 foo.2. 若对 wrapper() 的调用传递 const 左值string ,则推导 T 为 const string& ,且 std::forward 确保将 const 左值引用传递给 foo.3. 若对 wrapper() 的调用传递非 const 左值string ,则推导 T 为string& ,且 std::forward 确保将非 const 左值引用传递给 foo. 

分析:

1. 若对 wrapper() 的调用传递右值string ,则推导 T 为 std::string(非string& 或string&& ,且 std::forward 确保将右值引用传递给 foo.

2. 若对 wrapper() 的调用传递 const 左值string ,则推导 T 为 const string& ,且 std::forward 确保将 const 左值引用传递给 foo.

3. 若对 wrapper() 的调用传递非 const 左值string ,则推导 T 为string& ,且 std::forward 确保将非 const 左值引用传递给 foo.

举例

 1 #include<iostream>
 2 #include<utility>
 3 using namespace std;
 4
 5 void g(int &&i, int &j)
 6 {
 7     cout << i << " " << j << endl;
 8 }
 9
10 void f(int v1, int &v2)
11 {
12     cout << v1 << " " << ++v2 << endl;
13 }
14
15 //flip1实现不完整:顶层const和引用都丢掉了
16 template <typename F, typename T1, typename T2>
17 void flip1(F f, T1 t1, T2 t2)
18 {
19     f(t2, t1);
20 }
21
22 template <typename F, typename T1, typename T2>
23 void flip2(F f, T1 &&t1, T2 &&t2)
24 {
25     f(t2, t1);
26 }
27
28 template <typename F, typename T1, typename T2>
29 void flip(F f, T1 &&t1, T2 &&t2)
30 {
31     f(std::forward<T2>(t2), std::forward<T1>(t1));
32 }
33
34 int main()
35 {
36     int i = 0, j = 0, k = 0, l = 0;
37     cout << i << " " << j << " " << k << " " << l << endl;
38     f(42, i);         //f改变其实参i
39     flip1(f, j, 42);  //通过flip1调用f不会改变j
40     flip2(f, k, 42);  //正确:k被改变了
41     g(42, i);
42     flip(g, i, 42);   //正确:第三个参数的右值属性被保留了
43     cout << i << j << " " << k << " " << l << endl;
44     return 0;
45 }

重载与模板

转载于:https://www.cnblogs.com/sunbines/p/9375847.html

002 模板实参推断、重载与模板相关推荐

  1. C++知识点62——模板实参推断与函数模板的特化

    一.函数指针与模板实参推断 可以用函数模板初始化一个函数指针或给一个函数指针赋值 示例 template <typename T> int comp(const T &a, con ...

  2. C++ Primer 5th笔记(chap 16 模板和泛型编程)模板实参推断

    1. 模板实参推断( template argument deduction) 在模板实参推断过程中, 编译器使用函数调用中的实参类型来寻找模板实参, 用这些模板实参生成的函数版本与给定的函数调用最为 ...

  3. 模板进阶——模板实参推断

    一.关键点 模板实参:模板参数T的实例类型,如int.string等 模板实参推断:从函数实参来确定模板实参的过程 模板类型参数与类型转换:const的转换.数组/函数到指针的转换 显式模板实参:当模 ...

  4. C++ Primer 5th笔记(chap 16 模板和泛型编程)模板实参推断和引用

    template < typename T> void f (T &p) 函数参数p是一个模板类型参数T的引用, 编译器会应用正常的引用绑定规则: const 是底层的, 不是顶层 ...

  5. 【第十六章】模板实参推断

    二.模板显式推断 在C++中,若函数模板返回类型需要用户指定,那么在定义函数模板时,模板参数的顺序是很重要的,如下代码: template <typename T1, typename T2, ...

  6. C++模板学习笔记——模板实参

    对于函数模板,编译器通过隐式推断模板实参.其中,从函数实参来确定模板实参的过程被称为模板实参推断.在模板实参推断过程中,编译器使用函数调用中的实参类型来寻找模板实参,用这些模板实参生成的函数版本与给定 ...

  7. C++编程进阶7(何时使用成员函数模板,模板类的实参推断与类型转换、继承与数组)

    二十六.何时使用成员函数模板 关于成员函数模板见https://blog.csdn.net/Master_Cui/article/details/111824152 成员函数模板主要用来兼容不同类型的 ...

  8. C++ Primer 5th笔记(chap 16 模板和泛型编程)重载与模板

    1. 定义 函数模板可以被另一个模板或一个普通非模板函数重载: 名字相同的函数必须具有不同数量或类型的参数 1.1 函数模板匹配因素 对于一个调用, 其候选函数包括所有模板实参推断成功的函数模板实例. ...

  9. [014]模板-模板实参推导

    对于函数模板,编译器利用调用中的函数实参来确定其函数模板,从函数实参来确定模板实参的过程就被叫做是模板实参推导. 比如: 1 #include<iostream> 2 #include&l ...

最新文章

  1. 2021-09-30
  2. Lang.String
  3. mysql查询条件是小数 查不到6.28_28.mysql数据库之查询
  4. 如何合并多个(.txt或其他)文件到一个文件
  5. 高德上线 “家人地图”功能 家人可随时查看彼此的位置
  6. 《从零开始学Swift》学习笔记(Day 32)——计算属性
  7. 献给初学破解人的口诀和指令
  8. 买什么手提电脑好_玉米种子买什么品种好?
  9. oracle ebs form视频,Oracle EBS教学视频
  10. android qq轻聊版多个,Android QQ轻聊版怎样样
  11. 支持M1芯片AE2022已发布,After Effects 2022 for MAC中文安装教程,支持Monterey系统不闪退
  12. cve 爬虫_CVE监控之Python代码实现
  13. android文字转语音模板,Android-文字转语音
  14. 关于等值连接,自然连接的理解
  15. 华硕电脑笔记本台式机预装专用系统 V2011
  16. 应用程序无法正常启动(0xC0000142)
  17. java 绘图板_非常值得学习的java 绘图板源代码
  18. 非985/211面试大厂校招经历经验总结(安全工程师/渗透工程师)
  19. 30套免费的响应式 HTML5 CSS3 模板下载
  20. 进程、线程、协程之间的关系

热门文章

  1. mac中修改系统限制量--ulimit和sysctl
  2. redis生产环境持久化_在SageMaker上安装持久性Julia环境
  3. 拉5000万存款,银行客户经理能拿40万奖金?
  4. 农村房屋能抵押做贷款吗?
  5. 台湾印象之三:吃与喝
  6. scrum回顾_3步开好回顾会 | IDCF FDCC认证学员作品
  7. python 按月份分组_django ORM queryset按月、周、TruncMonth分组
  8. css before after用法_CSS 伪元素基础知识:content 与counter 实用技巧(二)
  9. java s1_转!!Java 基础面试题的剖析: short s1=1;s1 = s1 +1 报错? s1+=1 呢
  10. Catlike Coding网站文章解析 -- 2.Procedural Grid