What is the difference between the following two methods of transmitting parameters?
template & lt; TypeName ... Args & gt; SMTH (Args & amp; & amp; ... args): Base (Args ...) {}
template & lt; TypeName ... Args & gt; SMTH (Args & amp; & amp ... args): base (std :: forward & lt; args & gt; (args) ...) {}
Answer 1, Authority 100%
Suppose that the base
constructor accepts a MOVE-only parameter value:
struct base {
Base (STD :: UNIQUE_PTR & LT; Int & GT; Value);
};
In this case, the first option is not compiled:
template & lt; TypeName ... Args & gt; SMTH (Args & amp; & amp; ... args): Base (Args ...) {}
Attempt to make a copy ^^^^
Here you can write STD :: Move
and it will work:
template & lt; TypeName ... Args & gt; SMTH (Args & amp; & amp; ... args): Base (std :: Move (Args) ...) {}
However, if Base
two constructors, one of which moves the value, and the other takes the link:
struct base {
Base (STD :: UNIQUE_PTR & LT; int & gt; & amp; & amp; value);
BASE (STD :: UNIQUE_PTR & LT; Int & gt; & amp; value);
};
And if we want smth
to base
it is those types of arguments with which it was called, then std :: Move
we don’t Suitable – it will always turn the argument in the R-VALUE link.
For this, there is std :: forward & lt; t & gt;
, which saves the original type of argument:
struct smth: base {
TEMPLATE & LT; TypeName ... Args & GT; SMTH (Args & amp; & amp ... args): base (std :: forward & lt; args & gt; (args) ...) {}
};
STD :: UNIQUE_PTR & LT; INT & GT; p;
SMTH S1 (P); // OK, will be called Base (STD :: UNIQUE_PTR & LT; INT & GT; & amp;);
SMTH S2 (ST :: MOVE (P)); // OK, will be called Base (STD :: UNIQUE_PTR & LT; INT & GT; & amp; & amp;);
Note: STD :: FORWARD & LT; T & GT; (T)
only works with “universal references”, i.e. where T
– this parameter is a function template (designer), and t
– the argument of this function with the type T & amp; & amp;
(a special exception to the language such type T & amp; & amp;
is not an r-value reference, and makes T
repeat type that passed into the function)
.