I have a lambda that either appends an object and returns it or it returns an already existing object. On GCC, i receive the error:
cannot bind non-const lvalue reference of type 'T&' to an rvalue of type 'T'
Here is an example:
#include <iostream>
#include <cstdlib>
#include <functional>
struct foo {
int a;
};
int main() {
std::vector<foo> foos = {foo{22}};
std::size_t new_index = -1;
bool append = (rand() & 1) == 1;
//compiler error in next line
foo& new_foo = std::invoke([&foos,&new_index,append](){
if(append) {
new_index = foos.size();
return foos.emplace_back();
}else {
new_index = 0;
return foos[new_index];
}
});
return new_foo.a;
}
In this example new_foo
is supposed to be mutated after retrieving the object, hence const foo& new_foo
is not an option.
CodePudding user response:
return type of lambda is not a reference by default, you have to specify it with trailling return type( -> foo&
, -> decltype(auto)
):
[&foos, &new_index, append]()-> foo& { /*..*/ }
or return a type which handles reference (as std::reference_wrapper
):
[&foos,&new_index,append]() {
if(append) {
new_index = foos.size();
return std::ref(foos.emplace_back());
} else {
new_index = 0;
return std::ref(foos[new_index]);
}
}