Вот две функции, которые предоставляют результат:
Foo provideFooAsTemporary()
{
return Foo{};
}
Foo& provideFooAsReference()
{
static Foo foo{};
return foo;
}
Вот ошибочная идеальная переадресация:
template
decltype(auto) erroneousForwardFoo(TFn&& fn)
{
auto&& result = fn();
// do some stuff here
return std::forward(result);
}
Foo fooTemporary = erroneousForwardFoo(provideFooAsTemporary); // fails
Foo& fooReference = erroneousForwardFoo(provideFooAsReference); // works
Если результат является временным, пересылка завершается неудачей, о чем свидетельствует результат erroneousForwardFoo, указывающий на недопустимую память.
Напротив, следующий упрощенный код пересылки работает просто великолепно:
template
decltype(auto) workingForwardFoo(TFn&& fn)
{
return fn();
}
Foo fooTemporary = workingForwardFoo(provideFooAsTemporary); // works
Foo& fooReference = workingForwardFoo(provideFooAsReference); // works
Однако я хочу «сделать кое-что» перед возвратом, поэтому мне нужно исправить ошибку ForwardFoo.
Отладка показала что проблема в висящей ссылке (см. пример godbolt). Насколько я понимаю, это связано с тем, что время жизни временного объекта привязано к результату ссылки на rvalue, и, к сожалению, перемещение этого не меняет.
Теперь вопросы:
- Каково подробное и точное объяснение того, что происходит не так?
- Как я могу переписать erroneousForwardFoo в экономичный способ добиться правильной общей реализации?
Хотя я привел только пример кода для пересылки ссылки на lvalue я хочу, чтобы решение также поддерживало ссылки на rvalue:
Foo&& provideFooAsRValueReference()
{
static Foo foo{};
return std::move(foo);
}
Подробнее здесь: https://stackoverflow.com/questions/787 ... n-s-result