c++11 perfect forwarding
完美转发是c++11 引入右值引用之后,在template 中的延伸. 顾名思义,完美转发是将参数不改变属性的条件下,转发给下一个函数. 因为普通函数的参数一旦具名,始终都是lvalue. 如果把rvalue转发到下一个函数上的参数中,还是rvalue.这就是完美转发的目的。
#include<iostream>
using namespace std; struct X {};
void inner(const X&) {cout << "inner(const X&)" << endl;}
void inner(X&&) {cout << "inner(X&&)" << endl;}
template<typename T>
void outer(T&& t) {inner(forward<T>(t));} int main()
{
X a;
outer(a);
outer(X());
inner(forward<X>(X()));
}
//inner(const X&)
//inner(X&&)
//inner(X&&)
那么如何支持完美转发呢?第一反应就是用通用引用;假设如此实现:
template<class T>
T&& forwarding(T&& t){
return static_cast<T&&>(param);
}
传入左值的时候是forward(x), 传入右值是forward(X()),看起来符合要求。但是这里用错了完美转发的具体场景,也就是通常我们用完美转发是什么形式呢?如果不使用完美转发,那么在template function会出现什么情况?
template <typename T>
void relay(T&& t) {
cout << "in relay" << endl;
func(t);
}
relay(temp());传入的是右值,但是转发的时候t被认为左值. 不符合完美转发语义
template<typename T>
void foo(T&& fparam)
{
std::forward<T>(fparam);
}
以上是完美转发的场景,完美转发配套通用引用,才是它的应用场景, 因为param已经具名,所以是lvalue,刚才的简单实现,显然不符合。
template <typename T>
T&& forward(typename remove_reference<T>::type& param)
{
return static_cast<T&&>(param);
}
以上实现,才是完美转发的主要实现,为什么是主要实现,因为它是最多场景的实现。我们分析一下foo(A());T被推导为A,fparam是lvalue,param是A&。因此匹配
但是如果我们翻C++ 完美转发的实现:貌似还有另外一个实现:
template <class T> T&& forward(typename remove_reference<T>::type&& t) noexcept;
这里应对什么场景呢?直接调用forward<A>(A())的场景。 注意这里typename remove_reference<T>::type&&不再是通用引用,而是右值引用。之前的左值引用,不能接右值,所以需要重定义一个函数. 以上就实现了完美转发的所有内容.完美转发的根基是引用折叠和通用引用.
template< class T > struct remove_reference {typedef T type;};
template< class T > struct remove_reference<T&> {typedef T type;};
template< class T > struct remove_reference<T&&> {typedef T type;};
c++11 perfect forwarding的更多相关文章
- 翻译「C++ Rvalue References Explained」C++右值引用详解 Part8:Perfect Forwarding(完美转发):解决方案
本文为第八部分,目录请参阅概述部分:http://www.cnblogs.com/harrywong/p/cpp-rvalue-references-explained-introduction.ht ...
- C++11--右值引用(Perfect Forwarding)
/* * 右值引用 2: Perfect Forwarding */ void foo( boVector arg ); // boVector既有移动构造又有拷贝构造 template< ty ...
- C++: Perfect Forwarding
Link: Rvalue References and Perfect Forwarding in C++0x (https://www.justsoftwaresolutions.co.uk/cpl ...
- 完美转发(perfect forwarding)、universal reference、引用折叠(collasping)
首先要分清: C++里的值只有两种值:左值.右值.—— 其本质应该是内存中存储的值/instance分两种:一种是持久的,一种是“短暂的” 也只有两种引用: 左值引用.右值引用. ——引用,就是这个内 ...
- Effective Modern C++ 42 Specific Ways to Improve Your Use of C++11 and C++14
Item 1: Understand template type deduction. Item 2: Understand auto type deduction. Item 3: Understa ...
- 【转】C++11 标准新特性: 右值引用与转移语义
VS2013出来了,对于C++来说,最大的改变莫过于对于C++11新特性的支持,在网上搜了一下C++11的介绍,发现这篇文章非常不错,分享给大家同时自己作为存档. 原文地址:http://www.ib ...
- c++11 中的 move 与 forward
[update: 关于左值右值的另一点总结,请参看这篇] 一. move 关于 lvaue 和 rvalue,在 c++11 以前存在一个有趣的现象:T& 指向 lvalue (左传引用), ...
- [转载] C++11新特性
C++11标准发布已有一段时间了, 维基百科上有对C++11新标准的变化和C++11新特性介绍的文章. 我是一名C++程序员,非常想了解一下C++11. 英文版的维基百科看起来非常费劲,而中文版维基百 ...
- C++ 11和C++98相比有哪些新特性
此文是如下博文的翻译: https://herbsutter.com/elements-of-modern-c-style/ C++11标准提供了许多有用的新特性.这篇文章特别针对使C++11和C++ ...
随机推荐
- 为什么要使用href=”javascript:void(0);”
为什么要使用href=”javascript:void(0);” href=”javascript:void(0);”这个的含义是,让超链接去执行一个js函数,而不是去跳转到一个地址,而void( ...
- 优化mysql slave的同步速度
测试环境:Red Hat Enterprise Linux Server release 6.3 (Santiago)Server version: 5.6.22-log MySQL Communit ...
- ajax+servlet 简易时间效果
<!DOCTYPE html> <html> <head> <title>index.html</title> <meta name= ...
- c#反射泛型方法
private void GetByEnumType() { var EnumType = Context.Request["EnumType"] ?? ""; ...
- Spring MVC 小计
前端控制器是DispatcherServlet 应用控制器 1 处理器映射器(Handler Mapping) 进行处理器管理 2 视图解析器(View Resolver) ...
- Java中的Set,List,Map的区别
1. 对JAVA的集合的理解是想对于数组 数组是大小固定的,并且同一个数组只能存放类型一样的数据(基本类型/引用类型) JAVA集合可以存储和操作数目不固定的一组数据. 所有的JAVA集合都位于 ja ...
- 白盒测试实践项目(day1)
由于近期各种考试逼近,我们小组白盒测试实践项目进度有些慢,在任务决定后的两天里,我们小组各个成员的进度完成不一. 胡俊辉熟悉了怎么使用Junit对部分代码的测试,初步掌握了Junit的简单使用. 汪鸿 ...
- sublime 3插件安装记录
安装sublime 3的package control管理器: 从菜单 View - Show Console 或者 ctrl + ~ 快捷键,调出 console.将以下 Python 代码粘贴进去 ...
- CodeForces 682B Alyona and Mex (题意水题)
题意:给定一个序列,你可以对这里面的数用小于它的数来代替,最后让你求,改完后的最大的序列中缺少的最小的数. 析:这个题,读了两个多小时也没读懂,要是读懂了,肯定能做出来...没什么可说的,就是尽量凑1 ...
- 编写高质量代码改善C#程序的157个建议——建议112:将现实世界中的对象抽象为类,将可复用对象圈起来就是命名空间
建议112:将现实世界中的对象抽象为类,将可复用对象圈起来就是命名空间 在我们身边的世界中,对象是什么?对象就是事物,俗称“东西”.那么,什么东西算得上是一个对象呢?对象有属性.有行为.以动物为例,比 ...