Document directory
- Prerequisites
- STD: Move
- STD: Forward
STD: Move and STD: forward are new standard library functions in C ++ 0x, which are used to implement Mobile semantics and perfect forwarding respectively.
Let's analyze the specific implementation of these two functions in gcc4.6.
Prerequisites
- Reference folding rules:
X & + & => X &
X & + & => X &
X & + & => X &
X & + & => X &&
- Function template parameter derivation rules (reference parameters on the right ):
This rule applies when the template parameter of the function template is t and the function parameter is T & (reference to the right value.
If the real parameter is left U &, the template parameter T should be derived as the reference type U &.
(According to the reference folding rule, u & + & => U &, and T & <=> U &, so t <=> U &)
If the real parameter is the right value U &, the template parameter T should be deduced as a non-reference type U.
(According to the reference folding rule, U or U & + & => U &, while T &&, therefore, T <=> U or U &, which is mandatory here t <=> U)
- STD: remove_reference is a meta function in the C ++ 0x standard library. Its function is to remove references in the type.
STD: remove_reference <u & >:: type <=> U
STD: remove_reference <u & >:: type <=> U
STD: remove_reference <u >:: type <=> U
- The following syntax converts expression T to the right value of the T type (specifically, it is a reference to the right value of the unknown)
Static_cast <t &> (t)
- Note: <=> in this article, the meaning is "that is, equivalent to".
STD: Move
Function
STD: Move (t) is responsible for converting expression T to the right value. Using this conversion means that you no longer care about t content, it can be moved (stolen) to solve the mobile semantic problem.
Source code and test code
template<typename _Tp> inline typename std::remove_reference<_Tp>::type&& move(_Tp&& __t) { return static_cast<typename std::remove_reference<_Tp>::type&&>(__t); }
#include<iostream>using namespace std;struct X {};int main(){X a;X&& b = move(a);X&& c = move(X());}
Code Description
- Row 9th of the test code uses the left value a of the X type to test the move function. According to the right value of the standard X type, reference B can only bind the right value of the X type, so move () the return value must be the right value of the X type.
- Row 10th of the test code uses the right value x () of the X type to test the move function. C can only be bound to the right value of the X type according to the reference of the right value of the standard X type, therefore, the return value of move (x () must be the right value of the X type.
- First, we will analyze the situation where the move function is called with the left value parameter, such as move (.
- Simulate a single-step call to the source code line 3rd, _ TP & <=> X &, _ T <=>.
- According to the parameter deduction rules of the function template, _ TP & <=> X & available _ TP <=> X &.
- Typename STD: remove_reference <_ TP >:: type <=> X.
Typename STD: remove_reference <_ TP>: Type & <=> X &&.
- One-step call again to go to the source code line 4th where the move function object is located.
- Static_cast <typename STD: remove_reference <_ TP >:: type &> (_ t) <=> static_cast <X &> ()
- According to the standard static_cast <X &> (A), the left value a is converted to an unnamed right value reference of the X type.
- Then we will analyze the situation of moving (x () using the right value parameter to call the move function.
- Simulate a single-step call to the source code line 3rd, _ TP &, _ T <=> X ().
- According to the parameter deduction rules of the function template, _ TP & amp; lt; & gt; X & amp; release _ TP <= & gt; X.
- Typename STD: remove_reference <_ TP >:: type <=> X.
Typename STD: remove_reference <_ TP>: Type & <=> X &&.
- One-step call again to go to the source code line 4th where the move function object is located.
- Static_cast <typename STD: remove_reference <_ TP >:: type &> (_ t) <=> static_cast <X &> (x ())
- According to the standard static_cast <X &> (x (), the right value x () is converted to an unnamed right value reference of the X type.
- We can see from 9 and 16 that the specific implementation of the STD: Move function in the source code complies with the standard,
Because no matter whether the left value A or the right value x () is used as a parameter to call the STD: Move function,
This implementation will return an unnamed right value reference (one of the right values), which complies with the definition of this function in the standard.
STD: Forward
Function
STD: Forward <t> (u) has two parameters: T and U. When T is the reference type of the Left value, U is converted to the left value of the T type. Otherwise, U is converted to the right value of the T type. STD: Forward is defined to solve the perfect parameter forwarding problem in the function template that uses the right value to reference the parameter.
Source code and test code
/// forward (as per N3143) template<typename _Tp> inline _Tp&& forward(typename std::remove_reference<_Tp>::type& __t) { return static_cast<_Tp&&>(__t); } template<typename _Tp> inline _Tp&& forward(typename std::remove_reference<_Tp>::type&& __t) { static_assert(!std::is_lvalue_reference<_Tp>::value, "template argument" " substituting _Tp is an lvalue reference type"); return static_cast<_Tp&&>(__t); }
#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(const X&)//inner(X&&)
Code Description
- Line 2 of the test code uses the left value of X type A to test the forward function. The program output indicates that outer (a) calls the inner (const X &) version, this proves that when the function template outer calls the forward function to forward the left value of parameter A to the inner function, the left Value Attribute of parameter A is successfully retained.
- Line 10 of the test code uses the right value of X () to test the forward function. The program output shows that outer (x () calls the inner (X &) version, this proves that when the function template outer calls the forward function to forward the right value x () of the parameter to the inner function, the right value attribute of the parameter x () is successfully retained.
- First, we will analyze the situation that outer (a) calls the forward function to forward the left value parameter.
- Simulate a one-step call to the test code line 8th, T & <=> X &, T <=>.
- According to the parameter deduction rules of the function template, T & <=> X & T <=> X & is available &.
- Forward <t> (t) <=> forward <X &> ().
- The second one-step call enters the source code line 4th or line 9th of the forward function entity.
- First try to match the forward function of source code 4th line, _ TP <=> X &.
- Typename STD: remove_reference <_ TP >:: type <=> X.
Typename STD: remove_reference <_ TP>: Type & <=> X &.
- The parameter _ t is of the same type as the parameter A. Therefore, the function is matched successfully.
- Then try to match the forward function of source code line 9th, _ TP <=> X &.
- Typename STD: remove_reference <_ TP >:: type <=> X.
Typename STD: remove_reference <_ TP>: Type & <=> X &&.
- The type of the parameter _ t is different from that of the real parameter A. Therefore, function matching fails.
- From 10 and 13, we can see 7. The forward function of source code 4th is actually called in one step.
- Static_cast <_ TP &> (_ t) <=> static_cast <X &> (a) <=>.
- Inner (Forward <t> (t) <=> Inner (static_cast <X &> (A) <=> Inner ().
- Outer (a) <=> Inner (Forward <t> (t) <=> Inner ()
The next one-step call will go to the inner (const X &) version of line 5th of the test code. The left value parameter is successfully forwarded.
- Then, we will analyze the situation that outer (x () calls the forward function to forward the right value parameter.
- Simulate a one-step call to test the code line 8th, T & amp; lt; & amp; T & amp; lt; = & gt; X ().
- According to the parameter deduction rules of the function template, T & <=> X & T <=> X is available.
- Forward <t> (t) <=> forward <x> (x ()).
- The second one-step call enters the source code line 4th or line 9th of the forward function entity.
- First try to match the forward function of source code 4th line, _ TP <=> X.
- Typename STD: remove_reference <_ TP >:: type <=> X.
Typename STD: remove_reference <_ TP>: Type & <=> X &.
- The parameter _ t is different from the real parameter x () type, so function matching fails.
- Then try to match the forward function of source code 9th, _ TP <=> X.
- Typename STD: remove_reference <_ TP >:: type <=> X.
Typename STD: remove_reference <_ TP>: Type & <=> X &&.
- The parameter _ t is of the same type as the real parameter x (). Therefore, the function is matched successfully.
- From 25 and 28, we can see that 22. The forward function of source code 9th is actually called in one step.
- Static_cast <_ TP &> (_ t) <=> static_cast <X &> (x () <=> X ().
- Inner (Forward <t> (t) <=> Inner (static_cast <X &> (x () <=> Inner (x ()).
- Outer (x () <=> Inner (Forward <t> (t) <=> Inner (x ())
The next one-step call will go to the inner (X &) version of line 6th of the test code. the right value parameter is successfully forwarded.
- From 17 and 32, we can see that the specific implementation of the STD: Forward function in the source code complies with the standard,
Because no matter whether the left value A or the right value x () is used as a parameter to call the function template outer with the right value reference parameter,
You only need to use the STD: Forward function to forward parameters in the outer function,
The left and right values of parameters can be retained to achieve perfect forwarding of function template parameters.