In the code snipped below, the compiler silently casts the return-by-copy function pointer into a return-by-const-reference std::function. When the std::function instance is called, a reference to the copy is returned and the application crashes (most of the time ;).
By the way of comparison, ordinary function pointers don't allow this implicit cast, so I wonder if I should go off complaining to the compiler vendor (gcc 4.8 in this case), or is this behaviour mandated by the standard?
#include <iostream>
#include <functional>
typedef std::function<const std::string&(const std::string& x)> F;
std::string bad(const std::string& x) { return x; }
const std::string& good(const std::string& x) { return x; }
typedef const std::string& (*FP)(const std::string&);
int main(int, char**) {
std::cout << F(&good)("hello") << std::endl;
std::cout << F(&bad)("hello") << std::endl;
FP a = &good;
// FP b = &bad; Not allowed!
return 0;
}
P.S. This is a simplified version of a real world problem, where bad
was actually a lambda returning a member of some type:
typedef std::function<const std::string&(const X& x)> F;
F f = [](const X& x) { return x->member(); };
It took us a while to figure out that the return type of this lambda was deduced to std::string
, not const std::string&
, and that this was causing a crash.
x->member()
returnstd::string
orconst std::string&
? – Stasconst std::string&
, but for the purpose of return type deduction, it doesn't really matter if it's reference or copy - it will be deduced as copy (the decayed type) (see akrzemi1.wordpress.com/2012/03/27/gotchas-of-type-inference) – Jacek Sieka