std :: реализация хода - PullRequest
       7

std :: реализация хода

0 голосов
/ 08 сентября 2011

Я получил следующий фрагмент от microsoft

template <typename T> struct RemoveReference {
     typedef T type;
};

template <typename T> struct RemoveReference<T&> {
     typedef T type;
};

template <typename T> struct RemoveReference<T&&> {
     typedef T type;
};

template <typename T> typename RemoveReference<T>::type&& Move(T&& t) {
    return t;
}

...

remote_integer x = frumple(5);
remote_integer&& x1 = Move(x);

, и я получаю сообщение об ошибке C2440: «возврат»: не можетпреобразовать из 'remote_integer' в 'remote_integer &&' "

что-то изменилось в компиляторах?С std :: move все идет как надо.

1 Ответ

3 голосов
/ 08 сентября 2011

Причина, по которой ваш 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).

...