c++ - Why there are two signatures of std::forward? -
as stated @ cplusplus.com, std::forward
has 2 signatures:
template <class t> t&& forward (typename remove_reference<t>::type& arg) noexcept; template <class t> t&& forward (typename remove_reference<t>::type&& arg) noexcept;
the typical use of std::forward
preserve rvalueness while passing arguments other functions. let's illustrate example:
void overloaded(int &) { std::cout << "lvalue"; } void overloaded(int &&) { std::cout << "rvalue"; } template <typename t> void fwd(t && t) { overloaded(std::forward<t>(t)); }
when call fwd(0)
, t
deduces int
(t
has type int &&
). call std::forward<int>(t)
. result of call expression of type int &&
second version of overloaded
function selected , program prints "rvalue" standard output.
when call fwd(i)
(where int variable), t
deduces int&
(t
has type int &
). call std::forward<int&>(t)
. result of call (after applying reference collapsing rules) expression of type int &
first version of overloaded
function selected , program prints "lvalue" standard output.
in both these cases use first overload of std::forward
(the 1 taking typename remove_reference<t>::type& arg
). because if type of t
int &&
binds lvalue reference (because named variable of type "rvalue reference something" lvalue , lvalues can't bind rvalue reference).
question 1:
what second overload of std::forward
for? can think of practical example, uses overload taking arg
rvalue reference?
question 2:
cplusplus.com says:
both signatures return same as:
static_cast<decltype(arg)&&>(arg)
the problem have that, i'm pretty sure wrong. when try return first overload of std::forward
compilation error.
when fwd
called int
rvalue, calls first overload of std::forward
t = int
. then, decltype(arg)
become int&
static_cast<decltype(arg)&&>(arg)
collapse static_cast<int&>(arg)
. return type int &&
, compilation error:
cannot bind ‘std::remove_reference<int>::type {aka int}’ lvalue ‘int&&’
both overloaded versions of std::forward
should return static_cast<t&&>(arg)
. right?
do think quote cplusplus.com mistake?
class foo {}; auto f = [](){ return foo{}; }; auto g = []()->foo&{ static foo x; return x; }; template<class t> std::false_type is_rvalue( t& ) { return {}; } template<class t> std::true_type is_rvalue( t&& ) { return {}; } template<class t, class f> auto test( f&& f ) { return is_rvalue( std::forward<t>( f() ) ); } int main() { std::cout << test<foo>(f) << "," << test<foo&>(g) << "\n"; }
it bit contrived; imagine have factory might produce foo
or foo&
depending on unimportant details, know want forward based on second type t
t&&
. know if t
not reference, won't produce foo
, if t
reference might.
Comments
Post a Comment