", поскольку функция, которая принимает ссылку на rvalue, может принимать как ссылки на rvalue (неназванные временные ссылки), так и ссылки на lvalue (именованные неконстантные ссылки)"
Это неверное утверждение.На первых итерациях эталонной спецификации rvalue это было правдой, но она больше не применяется и реализуется, по крайней мере, в MSVC, чтобы соответствовать этому более позднему изменению.Другими словами, это недопустимо:
void f(char&&);
char x;
f(x);
Чтобы вызвать функцию, ожидающую ссылки rvalue с lvalue, вы должны превратить ее в значение r следующим образом:
f(std::move(x))
Конечноэтот синтаксис проясняет, в чем разница между функцией, принимающей ссылку lvalue, и функцией, использующей ссылку rvalue: ожидается, что ссылка rvalue не выдержит вызова.Это большое дело.
Теперь вы, конечно, можете создать новую функцию, которая будет делать то же самое, что и std :: move, и затем вы сможете «использовать» ссылки на rvalue, вроде ссылок на lvalue.Я думал о том, чтобы сделать это, например, с помощью структуры посетителя, которая иногда возникает, когда вас просто не волнует какой-либо результат вызова посетителя, но в других случаях вы делаете это и, следовательно, нуждаетесь в ссылке на lvalue в этих случаях.Со ссылкой на rvalue я мог бы получить и то, и другое ... но это такое нарушение семантики ссылок на rvalue, что я решил, что это плохая идея.
Ваше утверждение может быть путаницей на основании этого:
template < typename T >
void f(T&&);
char x;
f(x);
Это работает, но не потому, что вы передаете lvalue в качестве ссылки на rvalue.Это работает из-за затухания ссылок (также нового в C ++ 0x).Когда вы передаете lvalue в такой шаблон, он на самом деле создается, например, так:
void f<char&>(char&&&);
Распад эталона говорит о том, что &&&
превращается в &
, поэтому фактическое создание экземпляра выглядит так:1022 *
Другими словами, вы просто передаете lvalue по ссылке ... ничего нового или особенного в этом нет.
Надеюсь, что все прояснится.