I'm trying to get a lambda to return a reference to global. My MCVE is
static int frob;
int& foo();
template <typename F>
auto bar(F f)
{
return f();
}
int& foo()
{
return bar([&](){
return frob;
});
// int* p;
// bar([&](){
// p = &frob;
// });
// return *p;
}
Using the outcommented implementation of foo passes compilation, but otherwise I get (from gcc 12.2.0)
error: cannot bind non-const lvalue reference of type ‘int&’ to an rvalue of type ‘int’
I tried to create an int& inside foo to hold the reference to frob land (in hope that it would make the returned expression an int&), but that didn't help. Also moving frob into foo or even the lambda didn't help either, however it's not an alternative in my actual case anyway.
I'm a bit confused by the error so the question is first why do I get the error in the first place (and second how can I get around it, still transporting the result out of the lambda via return statement).
auto is deduced to T, not T& in both bar and lambda's return type. auto& would be necessary.
So you either have to use auto& annotations
static int frob;
int& foo();
template <typename F>
auto& bar(F f)
{
return f();
}
int& foo()
{
return bar([&]() -> auto&{
return frob;
});
}
or, alternatively, if you do not care about their true return types, std::ref can do the trick as it can carry references using value semantics and "unpack" them by implicit conversion to T& whenever necessary.
#include <functional>
static int frob;
int& foo();
template <typename F>
auto bar(F f)
{
return f();
}
int& foo()
{
return bar([&](){
return std::ref(frob);
});
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With