Здесь есть две проблемы.
Во-первых, вы на самом деле не вызываете лямбду, поэтому вместо передачи возвращенного значения в test
вы передаете объект функции, который явносовершенно несовместимый тип! Решите это, добавив ()
после лямбда-выражения для его вызова, передав таким образом возвращаемое значение test()
.
[](){ return 42; } ();
// ^^ now the whole expression has value 42
Во-вторых, вы правы, выведенный тип возврата будет B
, а не B&
, и временный объект может быть не привязан к аргументу ref-to-non- const
test(B&)
.
Одним из способов решения этой проблемы является использование конечного возвращаемого типачтобы вызвать ссылку:
[&a]() -> B& { .... }
Вы, кажется, знаете это, но не хотите этого делать. Почему?
Другой вариант - вернуть справочную оболочку, которая затем возвращается по значению, но ведет себя как ссылка:
return std::ref(a.getB()));
Другой вариант - изменить test
чтобы иметь возможность принять какое-то временное. Поскольку вам нужно это, чтобы иметь возможность изменять исходный объект, вы можете иметь test
взять указатель или другой тип со ссылочной семантикой (умный указатель, std::reference_wrapper<B>
, make B
имеют ссылочную семантику при копировании, ...)
void test(B* b) {
++(b->i);
}
...
test([&]() { return &a.getB(); } () );
Примечание для педантов: я знаю, что парены в ++(b->i)
не являются строго необходимыми. Я нахожу это более ясным.