2

Why is it necessary to explicitly indicate the type of template argument in std::forward?

template <class T> void foo (T&& x) {
    goo (x);                   // always an lvalue
    goo (std::forward<T>(x));  // rvalue if argument is rvalue
}

considering std::forward implementation:

template <typename T>
T&& forward(std::remove_reference_t<T>& x)
{
    return static_cast<T&&>(x);
}

and std::remove_reference implementation:

template< class T > struct remove_reference      {typedef T type;};
template< class T > struct remove_reference<T&>  {typedef T type;};

template< class T >
using remove_reference_t = typename remove_reference<T>::type;
Max Popov
  • 357
  • 2
  • 12
  • Are you asking what is it about the implementation that makes the type argument mandatory, as opposed to deduce? Or why is it required as a design choice? – StoryTeller - Unslander Monica Jan 23 '22 at 16:50
  • @StoryTeller-UnslanderMonica I'm trying to figure out why I can't write just `goo (std::forward(x));` – Max Popov Jan 23 '22 at 16:53
  • 1
    Because `forward` cannot deduce the type. In case of universal references, `f(T&&)`, the type `T` is actually the type of reference you call the function with. The `&&` is purely symbolic here. – ALX23z Jan 23 '22 at 17:03

1 Answers1

4

The argument's type in std::forward() is:

remove_reference<T>::type

Here T position is left of the scope resolution operator ::, which makes it a "non-deduced context" (see non-deduced context on cppreference). Because it is not automatically deduced, you have to provide the type yourself.

danadam
  • 3,350
  • 20
  • 18