杂货边角(25):完美转发
2018-02-28 18:40
176 查看
完美转发是C++11借助右值引用这个引入的特性而顺带完成的一个很美的特性,涉及到两个重要的概念:引用折叠和模板参数推导。
这里面最值得说的以及最容易混淆的莫过于引用折叠,这篇文章有很好的解释。举个简单的常见来说明:
其中值得注意的是,当采用完美转发特色&&解析模板形参时,调用时实参为左值时和为左值引用的情况一致。
#include <iostream> #include <type_traits> using namespace std; void RunCode(int && m ) { cout << "rvalue ref" << endl; } void RunCode(int & m) { cout << "lvalue ref" << endl; } void RunCode(const int && m) { cout << "const rvalue ref" << endl; } void RunCode(const int & m) { cout << "const lvalue ref" << endl; } template <typename T> void PerfectForward(T && t) { RunCode(forward<T>(t)); } //C++标准规定,具名的右值引用当作左值,故而这里必须得有forward<T>强制类型转换在, //不然直接写成RunCode(t)那么其中的t将被看做左值 template <typename T, typename U> void PerfectForward(T && t, U& Func) { cout << t << "\tforward..." << endl; Func(forward<T>(t)); } void RunPart(double&& m) { cout << "get inside " << __func__ << endl; } void RunHome(double&& h) { cout << "get inside " << __func__ << endl; } void RunComp(double&& c) { cout << "get inside " << __func__ << endl; } // 1. the return type (bool) is only valid if T is an integral type: template <class T> typename std::enable_if<std::is_integral<T>::value,bool>::type is_odd (T i) {return bool(i%2);} // 2. the second template argument is only valid if T is an integral type: template < class T, class = typename std::enable_if<std::is_integral<T>::value>::type> bool is_even (T i) {return !bool(i%2);} int main() { int a; int b; const int c = 1; const int d = 0; PerfectForward(a); PerfectForward(move(b)); PerfectForward(c); PerfectForward(move(d)); PerfectForward(1.5, RunComp); //不借助typeList‘< >’进行特化,而是直接传入参数进行特化 PerfectForward(8, RunPart); PerfectForward(1.5, RunHome); int i = 1; double j = 1.0; cout << std::boolalpha; //声明ostream中的所有bool量用true/false表示而非1/0,类比std::hex cout << "i is odd: " << is_odd(i) << endl; cout << "i is even: " << is_even(i) << endl; //cout << "j is odd: " << is_odd(j) << endl; //找不到匹配的函数 //cout << "j is even: " << is_even(j) << endl; //因为模板is_even的第二个参数无效,故而无法正常实例化,从而出现找不到匹配的函数for call to 'is_even(double&)` } /************************************************** **完美转发是一个很棒的机制。对于完美转发而言,右值引用并非“天生神力”,只是C++11引入了右值 **概念,因此为其新定了引用折叠的规则,以满足完美转发的需求 **************************************************/
这里面最值得说的以及最容易混淆的莫过于引用折叠,这篇文章有很好的解释。举个简单的常见来说明:
//完美转发函数 template <typename T> void PerfectForward(T && t) { T temp; //to-do ... } ... int a = 1; PerfectForward(a); int& la = a; PerfectForward(la); int&& ra = 10; PerfectForward(ra); //依次用左值,左值引用,右值引用调用转发函数,则T&& t实际的类型,以及模板参数T对应的类型规则如下:
模板形参t被声明的类型 | 调用时实际传入的实参类型 | 调用后形参t的实际类型 | 调用后T的实际类型 |
---|---|---|---|
T& | A& or A | A& | A |
T& | A&& | A& | A |
T&& | A& or A | A& | A& |
T&& | A&& | A&& | A |
相关文章推荐
- 《C++0x漫谈》系列之:右值引用或“move语意与完美转发”(上)
- 右值引用、完美转发
- 1030. 完美数列(25)
- 《C++0x漫谈》系列之:右值引用(或“move语意与完美转发”)(下)
- C++11新特性之 std::forward(完美转发)
- PAT BASIC LEVEL 1030. 完美数列(25)
- 1030. 完美数列(25)
- 【再思考】PATBasic——1030. 完美数列(25)
- 1030. 完美数列(25)
- Google Voice接收短信转发到手机的完美解决方法
- PAT-乙级-1030. *完美数列(25)
- C++11:深入理解右值引用,move语义和完美转发
- 我所知道的Move语义与完美转发
- 1030. 完美数列(25)
- PAT 1030 完美数列(25)
- 1030. 完美数列(25)-浙大PAT乙级真题java实现
- PAT 乙级 1030. 完美数列(25)
- [PAT乙级]1030. 完美数列(25)
- c++可变参数完美转发
- 《C++0x漫谈》系列之:右值引用或“move语意与完美转发”(下)