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

1.1 从左值引用函数参数推断类型

函数参数的类型

  • 一个普通( 左值) 引用时( 形如 T & )

绑定规则:传递一个左值( 一个变量或一个返回引用类型的表达式)。实参可以是 const 类型, 也可以不是。

如果实参是 const 的, 则 T 将被推断为 const 类型:
template <typename T> void f1 ( T& ) ; / / 实参必须是一个左值/ / 对 fl 的调用使用实参所引用的类型作为模板参数类型
fl (i); / / i 是一个int; 模板参数类型 T 是 int
fl (ci) ; // ci 是一个 const int; 模板参数 T 是 const int
fl (5 ); / / 错误: 传递给一个&参数的实参必须是一个左值
  • const T&
    绑定规则:可以传递给它任何类型的实参 个对象( const 或非 const)、 一个临时对象或是一个字面常量值。

  • 函数参数本身是 const 时,T 的类型推断的结果不会是一个const类型。 const已经是函数参数类型的一部分; 因此, 它不会也是模板参数类型的一部分:

template <typename T> void f2 (const T & ) ; / / 可以接受一个右值
// f2 中的参教是 const &; 实参中的 const 是无关的
// 在每个调用中, f2 的函数参数都被推断为 const int &
f2 (i); / / i是一个 int; 模板参数 T 是 int
f2 (ci) ; // ci 是一个 const int , 但模板参数 T 是 int
f2 (5 ) ; // 一个 const &参数可以绑定到一个右值; T 是 int

1.2 从右值引用函数参数推断类型

当一个函数参数是一个右值引用(形如 T &&)

绑定规则:传递给它一个右值。 类型推断过程类似普通左值引用函数参数的推断过程。 推断出的 T 的类型是该右值实参的类型:

template <typename T> void f3 (T &&) ;
f3 (42) ; // 实参是一个 int 类型的右值; 模板参数 T 是 int

1.3 引用折叠和右值引用参数

假定i是一个 int 对象, 我们可能认为像 f3(i) 这样的调用是不合法的。 毕竟,i是一个左值, 而通常我们不能将一个右值引用绑定到一个左值上。 但 C++语言在正常绑定规则之外定义了两个例外规则, 允许这种绑定。

1.3.1规则1

影响右值引用参数的推断如何进行。 当我们将一个左值( 如i) 传递给函数的右值引用参数, 且此右值引用指向模板类型参数( 如 T &&) 时, 编译器推断模板类型参数为实参的左值引用类型。 因此, 当我们调用 f3(i)时, 编译器推断 T 的类型为int&,而非int。
T 被推断为 int &看起来好像意味着 f3 的函数参数应该是一个类型int &的右值引用。

1.3.2 规则2

如果我们间接创建一个引用的引用, 则这些引用形成了‘‘ 折叠”。 在所有情况下( 除了一个例外), 引用会折叠成一个普通的左值引用类型。 在新标准中, 折叠规则扩展到右值引用。 只在一种特殊情况下引用会折叠成右值引用: 右值引用的右值引用。 即, 对于一个给定类型 X:

  • X & &、 X & & &和 X & & &都折叠成类型 X &
  • 类型 X & & & &折叠成 X & &
f3(i); //实参是一个左值; 模板参数 T 是int &
f3(ci); //实参是一个左值; 模板参数 T 是一个 const int &

当一个模板参数 T 被推断为引用类型时, 折叠规则告诉我们函数参数 T & &折叠为一个左值
引用类型。 例如, f3 (i) 的实例化结果可能像下面这样:

//无效代码. 只是用于演示目的
void f3<int &> (int & & & ); // 当 T 是 int &时, 函数参数为 int &

f3 的函数参数是 T&&且 T是int&, 因此T&&是int&&&, 会折叠成int&。 因此, 即使f3 的函数参数形式是一个右值引用(即T&&), 此调用也会用一个左值引用类型(即int&) 实例化 f3:

void f3<int&> (int & ); // 当 T 是 int &时, 函数参数折叠为 int &

这两个规则导致了两个重要结果:
• 如果一个函数参数是一个指向模板类型参数的右值引用( 如T&&), 则它可以被绑定到一个左值;
• 如果实参是一个左值, 则推断出的模板实参类型将是一个左值引用, 且函数参数将被实例化为一个( 普通) 左值引用参数(T &)

另外值得注意的是, 这两个规则暗示, 我们可以将任意类型的实参传递给 T&&类型的函数参数。 对于这种类型的参数, ( 显然) 可以传递给它右值, 而如我们刚刚看到的, 也可以传递给它左值

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

  1. C++ Primer 5th笔记(2)chapter 2变量和基本类型:引用、const

    1.引用refrence 定义:给对象起另外一个名字. 1.1 是两个类型一样的对象之间的: eg. int &i = 10;//错误double &f = i;//错误 引申:上面的 ...

  2. C++ Primer 学习笔记_75_模板与泛型编程 --模板定义

    模板与泛型编程 --模板定义 引言: 所谓泛型程序就是以独立于不论什么特定类型的方式编写代码.使用泛型程序时,我们须要提供详细程序实例所操作的类型或值. 模板是泛型编程的基础.使用模板时能够无须了解模 ...

  3. C++ Primer学习笔记-----第十六章:模板与泛型编程

    模板是C++中泛型编程的基础. 模板是蓝图,用来创建类型,创建的类型就是模板的实例,就好像我们用一个类型创建相应的实例一样. 函数模板 template<typename T> //模板参 ...

  4. C++ Primer 5th笔记(chap 16 模板和泛型编程)模板特例化

    1. 场景 //第一个版本:可以比较任意两个类型 template <typename T> int compare (const T &, const T & );//第 ...

  5. C++ Primer 5th笔记(chap 16 模板和泛型编程)可变参数模板

    1. 可变参数模板( variadic template) 一个接受可变数目参数的模板函数或模板类. 1.1 参数包 (parameter packet) 可变数目的参数被称为参数包,存在两种参数包: ...

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

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

  7. C++ Primer 5th笔记(chap 16 模板和泛型编程)函数模板显式实参

    1. 返回类型不清楚的时候,尾置返回允许我们在参数列表之后声明返回类型 template ctypename It> ??? & fcn (It beg, It end) {// 处理序 ...

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

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

  9. C++ Primer 5th笔记(chap 16 模板和泛型编程)成员模板

    1. 成员模板( member template) 一个类( 无论是普通类还是类模板) 可以包含本身是模板的成员函数. 成员模板不能是虚函数. 1.1 普通( 非模板 ) 类的成员模板 / / 函数对 ...

最新文章

  1. Docker在Ubuntu16.04和Windows10家庭版上安装操作步骤
  2. Unity插件之NGUI学习(4)—— 创建UI2DSprite动画
  3. C# 利用Jmail接收邮件
  4. 逆袭之旅DAY17.东软实训.Oracle.存储过程
  5. Android宫格动态列,Android实现宫格图片连续滑动效果
  6. CAN词典 - CANdictionary
  7. 守护线程Daemon的理解
  8. 带彩色字体的man pages(debian centos)
  9. 函数头文件php_PHP 7.4 的 FFI 将支持更好地在 PHP 中使用 C 函数/数据结构
  10. 机器学习基础 集成学习进阶(XGBoost+LightGBM)
  11. 巨人肩膀之线性表简介
  12. 二极管的分类、电路符号及万用表测发光二极管正负极
  13. 机房收费系统(二)之下机退卡
  14. 据说优秀的程序员都是这样送新年祝福的?
  15. matlab 的 符号,MATLAB符号计算
  16. 服务器ccc认证测试项目,CCC强制性认证包含哪些检测项目?
  17. 看尚电视adb安装当贝桌面,并开机自启
  18. 免费CDN加速服务 jsDelivr 支持npm,GitHub,WordPress
  19. 简单的web工程接收消息text--微信企业号
  20. 凡客:成于营销,败于营销

热门文章

  1. STEMA 考试每日一练 2020.12.7 - 2021.11.30 试题及答案 - 刷题
  2. Java 中静态代码块 static的作用及用法
  3. Linux什么是文件IO,linux中文件IO
  4. java 递归_Java的递归、如何与流相结合
  5. Python之sklearn-pmml:sklearn-pmml的简介、安装、使用方法之详细攻略
  6. AI:2020年6月21日北京智源大会演讲分享之09:20-09:40黄铁军教授《智源进展报告》
  7. ML之NB、LoR:基于NB和LoR算法对Kaggle IMDB影评数据集(国外类似豆瓣电影)情感分析进行分类
  8. Keras之ML~P:基于Keras中建立的简单的二分类问题的神经网络模型(根据200个数据样本预测新的5+1个样本)——类别预测
  9. CV之LabelImg:图片标注工具之LabelImg(图像标注工具)的简介、安装、使用方法详细攻略
  10. 7.3 TensorFlow笔记(基础篇):加载数据之从队列中读取