Причина, по которой ваш Move
не работает, заключается в том, что t
всегда lvalue (даже когда T&&
разрешает, скажем, int&&
). Даже если это может показаться странным, именованные ссылки на rvalue действительно являются lvalues.
Возвращаясь с вашего Move
, вы пытаетесь неявно связать lvalue со ссылкой на rvalue, что запрещено стандартом (§8.5.3). Как отмечено в комментариях, вы должны явно привести t
к rvalue reference.
Соответствующими частями стандарта являются §5 / 4 и §5 / 5, но я собираюсь процитировать примечание §5 / 6, в котором это хорошо суммируется:
Как правило, действие этого правила заключается в именованных ссылках rvalue.
обрабатываются как lvalues, а неназванные rvalue ссылки на объекты
рассматривается как значения x; rvalue ссылки на функции рассматриваются как
Значения по имени или без.
Правильная реализация действительно:
template <typename T>
typename std::remove_reference<T>::type&& move(T&& t)
{
return static_cast<typename std::remove_reference<T>::type&&>(t);
}
Насколько я помню, этот код был действителен в более ранних версиях. Но так как правила изменились, вы должны предоставить явное приведение сейчас (то же самое относится и к std :: forward).