Да, это эквивалент, но идиоматический способ - использовать простой T
.
Вот как forward
функции шаблонов определены в C++ 14:
1)
template< class T >
constexpr T&& forward(typename std::remove_reference<T>::type& t) noexcept;
2)
template< class T >
constexpr T&& forward(typename std::remove_reference<T>::type&& t) noexcept;
Во-первых, давайте изменим ваш пример немного, чтобы сделать типы менее запутанной:
template< typename U >
void foo(U&& in)
{
using T = U; // or U&&
bar(std::forward<T>(in));
}
Теперь, рассмотрим обратный тип forward
- T&&
, int
, используемый в качестве примера:
| U | T | T&& |
| int | int | int&& |
| int& | int& | int& && = int& |
| int&& | int&& | int&& && = int&& |
и using T = U&&
| U | U&& (also T) | T&& |
| int | int&& | int&& && = int&& |
| int& | int& && = int& | int& && = int& |
| int&& | int&& && = int&& | int&& && = int&& |
Таким образом, типы результатов одинаковы.
Что касается параметров, typename std::remove_reference<T>::type
- это мертвая подставка. Я использую remove_ref<T>
для читаемости:
| T | remove_ref<T> | remove_ref<T>& | remove_ref<T>&& |
| int | int | int& | int&& |
| int& | int | int& | int&& |
| int&& | int | int& | int&& |
Как вы можете видеть, это не зависит от референс-Несс параметра шаблона на всех.
Сводка об использовании объясняется более подробно here.
Эмпирическое испытание: http://melpon.org/wandbox/permlink/mJ0gobWkiplIRMMJ –