В приведенном ниже фрагменте кода компилятор молча преобразует указатель функции возврата по копии в функцию возврата по константной ссылке std::function. При вызове экземпляра 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&
, и что это вызывало сбой.
x->member()
возвращаетstd::string
илиconst std::string&
? - person Stas   schedule 25.04.2014const std::string&
, но для целей вывода типа возвращаемого значения не имеет большого значения, ссылка это или копия — она будет выведена как копия (распадающийся тип) (см. akrzemi1.wordpress.com/2012/03/27/gotchas-of-type-inference) - person Jacek Sieka   schedule 25.04.2014