The code below is not compilable due of auto deduction of the type returned from lambda.
what is a correct way to prevent this deduction in C++14 syntax terms without trailing type?
compilation error is about incompatible type (rvalue) on test() input which expects non-const reference
struct B {
int i;
};
struct A {
B &getB() { return b; }
private:
B b;
};
void test(B &b) {
b.i++;
}
int main() {
A a;
test([&a]() {
return a.getB();
});
return 0;
}
There are two problems here.
First, you don't actually call the lambda, so instead of passing the returned value into test
, you pass the function object, which is clearly a completely incompatible type! Solve this by adding ()
after the lambda to call it, thereby passing the return value to test()
.
[](){ return 42; } ();
// ^^ now the whole expression has value 42
Secondly, you are right, the deduced return type will be B
, not B&
, and the temporary object may not be bound to the ref-to-non-const
argument of test(B&)
.
One way around this would be to use a trailing return type to force a reference:
[&a]() -> B& { .... }
You seem to know this, but don't want to do it. Why?
Another option is to return a reference wrapper, which is then returned by value but behaves like a reference:
return std::ref(a.getB()));
Another option would be to change test
to be able to accept some temporary. Since you need this to be able to modify the original object, you could have test
take a pointer, or other type with reference semantics (a smart pointer, a std::reference_wrapper<B>
, make B
have reference semantics when you copy it, ...)
void test(B* b) {
++(b->i);
}
...
test([&]() { return &a.getB(); } () );
Note for pedants: I know the parens in ++(b->i)
aren't strictly necessary. I find it clearer.