2

Here is code below. Why if I replace typename remove_reference<S>::type& with S& it won't work nicely? (I mean a type will be deduced wrong)

If I pass an rvalue (let int be int), then S will be deduced as int, a's type is int&, forward() returns int&& (rvalue).

If I pass an lvalue (int) S will be deduced as int&, a's type is int& & ->int&, forward() returns int& &&->int&. everything works well, so why do we need that remove_reference?

template<class S>
S&& forward(typename remove_reference<S>::type& a) noexcept
{
  return static_cast<S&&>(a);
} 
David G
  • 94,763
  • 41
  • 167
  • 253
  • I'm not familiar with the intricacies of type deduction rules, but why do you think `S` could be deduced at all in this situation? Whatever the kind of reference or non-reference type one substitutes for `S`, the reference gets stripped and an lvalue reference type (possibly `const` if `S` is so, I imagine) results. Since different `S` give the same result, I think it would be reasonable if it were simply forbidden to try this kind of type "deduction". – Marc van Leeuwen Aug 29 '14 at 15:59

1 Answers1

8

Consider the original use case of forward:

template<class T>
void f(T&& t) { g(std::forward<T>(t)); }

t has a name, so it's an lvalue inside f even if it's bound to an rvalue. If forward is allowed to deduce type, then people would be tempted to write std::forward(t) and not actually get the perfect forwarding they expected.


Also, your analysis is not right. template<class S> void f(S& t); doesn't bind to rvalues. std::forward is actually a pair of overloads - the one you are referring to takes lvalues only, and

template <class T> constexpr T&& forward(remove_reference_t<T>&& t) noexcept;

handles rvalues.

T.C.
  • 133,968
  • 17
  • 288
  • 421
  • The `&` overload of `forward` could handle `rvalues` just fine, though, no? At least when used in the canonical forwarding context - precisely because `forward` itself only ever sees an lvalue in its argument - what *really* matters here is the explicit template parameter specification that makes forwarding work by casting to the right type. – Eli Bendersky Nov 04 '14 at 14:09