Próbowałem ciężko, aby funkcja lambda zwróciła wartość przez odniesienie bez tworzenia kopii odnośnej wartości. Mój przykładowy kod ilustruje problem. Kompiluje się i działa poprawnie, ale z "//" skomentowaną linią zamiast powyższą linią, tak nie jest. znalazłem dwa obejścia (oba przedstawione na moim przykładzie):Powrotna referencja lambda
- owinąć wynik z std :: Ref()
- zwracają wskaźnik zamiast odniesienie
Ale oba są obejścia nie to, czego naprawdę chcę i nie rozumiem, dlaczego są one konieczne: wyrażenie "makeRefA()" ma już typ, który zwraca funkcja lambda (const A &) i dlatego nie należy go kopiować ani konwertować. Nawiasem mówiąc: Konstruktor kopiowania jest naprawdę wywoływany, gdy go nie usuwam jawnie (co w moim "rzeczywistym" kodzie jest problemem wydajności). Dla mnie wygląda jak błąd kompilatora, ale próbowałem z kilkoma kompilatorami C++ 11, które wszystkie wykazują ten sam błąd. Czy jest coś wyjątkowego w odniesieniu do instrukcji "return" w funkcji lambda?
#include <functional>
#include <iostream>
struct A {
A(int i) : m(i) { }
A(const A&) = delete;
int m;
};
void foo(const A & a) {
std::cout << a.m <<'\n';
}
const A & makeRefA() {
static A a(3);
return a;
}
int main() {
std::function<const A&()> fctRef = [&]
{ return std::ref(makeRefA()); }; //compiles ok
//{ return makeRefA(); }; //error: use of deleted function 'A::A(const A&)'
foo(fctRef());
std::function<const A*()> fctPtr =
[&] { return &makeRefA(); };
foo(*fctPtr());
return 0;
}
wyjściowa:
3
3
"Zwróci referencję, gdy typ wyrażenia jest odniesieniem" <- Prawidłowe-ish. Wyrażenie * typ * nigdy nie będzie odniesieniem, ale otrzymasz właściwą odpowiedź, jeśli myślisz o tym w ten sposób. – Barry
odpowiedź, dziękuję! – Stefan
Działa nawet bez dodatkowych nawiasów, tj. std :: function fctRef = [&]() -> decltype (makeRefA()) {return makeRefA();}; –
Stefan