Глядя на страницы 200-201 Effective Modern C++ Скотта Мейера, предлагаемой упрощенной реализацией std::forward
может быть (правильная реализация была замечена в другом месте):
template <typename T>
T&& forward(std::remove_reference_t<T>& param)
{ return static_cast<T&&>(param); }
И при принятии виджета rvalue он становится:
Widget&& forward(Widget& param)
{ return static_cast<Widget&&>(param); }
Теперь, если вы возьмете этот замененный код и сделаете:
struct Widget { };
Widget&& forward(Widget& param)
{ return static_cast<Widget&&>(param); }
template <typename T>
void G(T&& uref)
{ }
template <typename T>
void F(T&& uref)
{ G(forward(uref)); }
int main()
{
Widget x;
F(std::move(x));
}
Что я не могу понять и еще не видел прямого ответа на SO, так это: в forward
как параметру Widget& param
удается принять Widget&&
из F()? Обычно gcc-5.0 будет жаловаться так с кодом без шаблона:
ошибка: недопустимая инициализация неконстантной ссылки типа «Widget&» из rvalue типа «std::remove_reference::type {aka Widget}»
(Вопрос № 27501400 почти касается темы, но не совсем. Он показывает, что стандарт имеет оба lvalue & и rvalue && версии.)
uref
- это lvalue. - person Jonathan Wakely   schedule 14.03.2015