I have the following simple C++20 program:
#include <iostream>
#include <string>
#include <utility>
#include <functional>
struct C {
std::string str = {"hello"};
const std::string& get() { return str; }
};
int main() {
C c;
std::function<const std::string&()> fun =
[&]() { return c.get(); };
std::cout << fun() << std::endl;
}
But when I compile with clang++ -std=c++20 -O0 -g t.cpp -o t and run it, I sometimes get garbage output like:
(@g
I am using clang++ 16.0.
std::function
that returns by reference?The lambda is indeed returning a (pr)value, not a reference.
This is warned about in the std::function
documentation on cppreference:
https://en.cppreference.com/w/cpp/utility/functional/function.html
Care should be taken when a
std::function
, whose result type is a reference, is initialized from a lambda expression without a trailing-return-type. Due to the way auto deduction works, such lambda expression will always return a prvalue. Hence, the resulting reference will usually bind to a temporary whose lifetime ends whenstd::function::operator()
returns.
(until C++23)If a
std::function
returning a reference is initialized from a function or function object returning a prvalue (including a lambda expression without a trailing-return-type), the program is ill-formed because binding the returned reference to a temporary object is forbidden.
(since C++23)
So, you need to explicitly declare your lambda as returning a reference, eg:
[&]() -> const std::string& { return c.get(); }
// ^^^^^^^^^^^^^^^^^^^^^