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).
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).
Share Improve this question edited 17 hours ago Some programmer dude 409k36 gold badges413 silver badges643 bronze badges asked 17 hours ago skykingskyking 14.4k2 gold badges37 silver badges61 bronze badges 2 |1 Answer
Reset to default 6auto
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);
});
}
bar
function returns the integer by value. If you want to return a reference you must explicitly say so (e.g.[&]() -> int& { return frob; }
) – Some programmer dude Commented 17 hours agoauto
works. – Passer By Commented 17 hours ago