В приведенном ниже коде компилятор молча переключает указатель функции возврата по копиям в функцию std:: return-by-const-reference. Когда вызывается экземпляр std:: function, возвращается ссылка на копию, и приложение вылетает (большую часть времени;).
Посредством сравнения обычные указатели функций не допускают этот неявный листинг, поэтому я задаюсь вопросом, следует ли мне с жалобой на поставщика компилятора (gcc 4.8 в этом случае), или это поведение задано стандартом?
#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. Это упрощенная версия проблемы реального мира, где bad
была фактически лямбдой, возвращающей член некоторого типа:
typedef std::function<const std::string&(const X& x)> F;
F f = [](const X& x) { return x->member(); };
Нам потребовалось некоторое время, чтобы выяснить, что тип возврата этой лямбды был выведен на std::string
, а не const std::string&
, и это вызвало сбой.