Consider this simplified example:
using MyVar = std::variant<int, float>;
using Container = std::vector<MyVar>;
static Container myContainer;
template <typename T> auto &JustOneType()
{
return myContainer |
std::ranges::views::filter([](auto &var) { return std::holds_alternative<T>(var); }) |
std::ranges::views::transform([](auto &var) -> auto & { return std::get<T>(var); });
}
void MyFun()
{
auto x = // This is fine
myContainer |
std::ranges::views::filter([](auto &var) { return std::holds_alternative<int>(var); }) |
std::ranges::views::transform([](auto &var) -> auto & { return std::get<int>(var); });
auto y = JustOneType<int>(); // This causes a compile error
}
Why does the line auto y
cause the following error?
error: cannot bind non-const lvalue reference of type.... to an rvalue of type...
But on the other hand, the line auto x
is completely fine.
You cannot return a reference to a prvalue.
Consider these two functions
auto& foo() {
int i = 1;
return i; // will dangle
}
auto& bar() {
return 1; // does not compile
}
While foo()
will compile and return a reference to an int
, the reference will dangle, as it is a reference to the temporary i
. bar()
on the other hand will not compile, because how could you take a reference to 1
(a prvalue)? You probably want auto func()
instead of auto& func()
.