Взглянем на следующий код:
#include<string>
#include<iostream>
using T = std::string;
void baz(T& v) { std::cout << v << std::endl; }
void boo(const T& v) { std::cout << v << std::endl; }
int main() {
baz( T("Passing an rvalue to be assigned to a lvalue&") ); //<--- This call is invalid
boo( T("Passing an rvalue to be assigned to a constant lvalue&") );
}
Стандарт сообщает нам, что первый вызов функции недействителен по очевидной причине, но второй вызов функции недействителен, потому что его можно интерпретировать как «Сгенерировать переменную, привязанную к области видимости функции boo, которая содержит lvalue, равное переданному rvalue. к функции ". По крайней мере, насколько я понимаю стандарт.
Однако добавление вспомогательных функций, таких как:
constexpr T &to_lvalue(T &&value) noexcept { return value; }
И вызываем функцию baz, используя ее для переноса параметров:
baz( to_lvalue( T("Passing a rvalue which will be transformed into an lvalue reference bound to the scope of baz") ) );
Считается совершенно правильным кодом и (насколько я понимаю) он в основном приводит к одному и тому же, а именно к построению lvalue, привязанного к области baz
Так почему бы компиляции просто не сгенерировать для вас этот код при вызове baz с rvalue? Он не требует накладных расходов во время выполнения, и поведение, кажется, хорошо определено. Что-то мне здесь не хватает? Или стандарт определен таким образом, чтобы не «по ошибке» использовать функцию, которая, как ожидается, изменит значение?
to_lvalue
, истекает после возвратаto_lvalue
, оставляя вам висящую ссылку. - person nwp   schedule 29.08.2017to_lvalue()
возвращает ссылку на временный объект, который выходит за пределы области видимости и уничтожается при возвратеto_lvalue()
. Таким образом, это неопределенное поведение. - person Sam Varshavchik   schedule 29.08.2017T&
temp с последующим вызовомbaz
в следующем операторе приводит к разрушенному объекту (MSVC установил его размер равным нулю, но более творческий код может вызвать сбой) - person Fire Lancer   schedule 29.08.2017T("Passing an rvalue to be assigned to a lvalue&")
доживает до конца выражения. Если сделать два шага, взорвется. Созданиеto_lvalue
приведет к еще большему количеству проблем, ИМХО. Ошибку компилятора исправить намного проще, чем случайные сбои из-за недиагностированного UB. - person NathanOliver   schedule 29.08.2017