W poniższym kodzie kompilator rzuca w milczeniu wskaźnik funkcji "powróć po kopii" do funkcji std :: return-by-const-reference. Kiedy wywoływana jest instancja std :: function, zwracane jest odwołanie do kopii, a aplikacja ulega awarii (przez większość czasu;).Czy funkcja std :: pozwala na niejawny rzut od odwołania do kopii w swoim typie zwracanym?
Dla porównania, zwykłe wskaźniki funkcji nie pozwalają na tę niejawną obsadę, więc zastanawiam się, czy powinienem złożyć skargę na dostawcę kompilatora (w tym przypadku gcc 4.8), czy też takie zachowanie jest nakazane przez 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;
}
PS: To jest uproszczoną wersją prawdziwych problemów świata, gdzie bad
faktycznie lambda powrocie członkiem jakiegoś typu:
typedef std::function<const std::string&(const X& x)> F;
F f = [](const X& x) { return x->member(); };
Zajęło nam trochę czasu, aby dowiedzieć się, że typ zwracany tej lambda została wyprowadzona do std::string
, a nie const std::string&
, co spowodowało awarię.
Czy 'x-> member()' zwraca 'std :: string' lub' const std :: string & '? – Stas
'const std :: string &', ale w celu odliczenia zwrotu, nie ma znaczenia, czy jest to odnośnik, czy kopia - zostanie to wydedukowane jako kopia (rodzaj zepsuty) (patrz http: //akrzemi1.wordpress .com/2012/03/27/gotyk-typu-wnioskowania /) –
Czy nazwałeś typy błędnie w tym ostatnim akapicie? A może źle zrozumiałem pytanie? –