模板实参推断和引用以及move和forward详解
来源:互联网 发布:淘宝网络电视机顶盒 编辑:程序博客网 时间:2024/05/18 03:31
模板实参推断和引用以及move和forward详解
从左值引用函数参数推断类型
当一个函数的参数是一个左值引用时,我们只能传递给它一个左值,实参可以是const类型或非const类型,实参是const,则T被推断为const。
例如:
template<typename T> void f1(T&);f1(i); //实参为int,则T推断为intf1(ci); //实参为const int,T推断为const intf1(5); //实参为右值,不能传入右值,错误
如果一个函数参数类型是const T&,正常绑定规则告诉我们可以给它传递任何类型实参–一个对象(const或非const)、一个临时对象或是一个字面常量值。当函数参数本身是const时,T的类型推断的结果不会是一个const类型,因为const已经是函数参数类型的一部分了,它不会再是模板参数类型的一部分。
template<typename T> void f2(const T&);f2(i); //i是int,则模板参数类型推断为intf2(ci); //i是const int,模板参数同样被推断为intf2(5); //一个const &参数可以绑定到右值,则T为int
从右值引用函数参数推断类型
当一个函数参数是一个右值引用时,显然我们可以传递一个右值给它。
template<typename T> void f3(T&&);f3(42); //实参是一个int型右值,模板参数类型为int
引用折叠和右值引用参数
我们同样可以将一个左值传给一个参数为右值引用的模板函数,此时编译器会推断模板类型参数为实参的左值引用类型,例如当我们调用f3(i)时,此时T被推断为int &,而非int。
此时就会出现引用的引用这种情况,这种情况下,这些引用会形成“折叠”,折叠成左值的引用或者右值的引用。
* X& &、X& &&、X&& &都被折叠成X&
* 类型X&& &&被折叠成X&&
f3(i); //实参是一个左值,模板参数T推断为int&,则参数i类型变为int& &&,由引用折叠得到为int&f3(ci); //实参是一个左值,模板参数T推断为const int&
编写接受右值引用参数的模板参数
template<typename T> void f3(T &&val){ T t = val;}
- 当我们对一个右值调用f3时,例如f3(43),T被推断为int,此时,局部变量t是int型,是val的一个拷贝。
- 当我们对一个左值调用f3时,T被推断为int &,此时t的类型是int&,t不是val的拷贝,而是val的一个引用。
move
标准库是这样定义move的:
template<typename t>typename remove_reference<T>::type&& move(T&& t){ return static_cast<typename remove_reference<T>::type&&>(t);}
当调用std::move(string(“bye”))时,实参为一个右值:
* 推断出T类型为string* remove_reference<string>::type为string* 将t强制转换为string&&并返回。
当调用std::move(s)时,s为一个左值:
* 推断出T类型为string&* 则t为string& &&,折叠成string&* remove_reference<string&>::type为string* 转换t为string&&,并返回
forward
除了move()语义之外,右值引用还需要解决的一个问题就是完美转发,转发问题针对的是模板函数,要求我们保持实参类型将其传递给其他函数。
forward原型类似如下:
template<class TYPE>TYPE&& forward(typename remove_reference<TYPE>::type& arg){ return static_cast<TYPE&&>(arg);}
通常情况下,我们使用forward传递那些定义为模板类型参数的右值引用的函数参数。通过其返回类型上的引用折叠,forward可以保持给定实参的左值/右值属性:
template<typename Type> intermediary(Type &&arg){ finalFcn(std::forward<Type>(arg));}当传入一个右值参数例如string("ss"):* Type会被推断为string,调用forward<string>* forward的返回类型TYPE&&为string&&* arg为remove_reference<string>::type&也就是string&类型* 再将arg强制为string&&类型返回,保持了arg的右值属性。当传入一个左值参数,例如string时:* Type推断为string&,则arg为string& &&类型,引用折叠得到string&类型。此时调用forward<string&>* forward返回值为string& &&,折叠为string&* arg为remove_reference<string&>::type& 为string&类型* 将arg转为string&返回,保持了arg的左值属性。
阅读全文
0 0
- 模板实参推断和引用以及move和forward详解
- C++primer学习:模板编程(6):模板实参推断和forward的运用与源代码
- 模版实参的推断和引用
- 模板实参推断与引用
- C++:模板实参推断及引用折叠
- 模板实参推断
- 模板实参推断
- 模板实参推断
- 模板实参推断
- 模板实参推断
- C++模板实参推断
- 模板实参推断
- std::move和std::forward
- std::move 和 std::forward
- 形参、实参以及值调用和引用调用的区别
- C++11 std::move和std::forward
- move和forward源码分析[转]
- C++11:std::move和std::forward
- 快速排序
- 最左前缀 联合索引
- 陈越姥姥 数据结构之树
- mysql的分页优化例子
- Git的使用--如何将本地项目上传到Github
- 模板实参推断和引用以及move和forward详解
- 如何在 Laravel 中 “规范” 的开发验证码发送功能
- 欢迎使用CSDN-markdown编辑器
- C++书目推荐
- 进程间通讯(四)共享内存
- 锁的重入
- 判断n以内所有素数
- Linux apt-get update/upgrade/install fetch error 出现404 问题
- Eclipse的一些使用技巧(1)