When trying to compiling this, suprisingly, it gives an error because the auto
parameter of the lambda function has been resolved to std::string
, and the compiler doesn't know how to convert std::string
to int
or Widget
when calling test
.
But, I wonder why the compiler has choosen the second invok
function instead of the first one, when the first one would succeed:
#include <string>
#include <functional>
struct Widget {};
bool test(int );
bool test(Widget );
void invok(std::function<bool(int)> ); // #1
void invok(std::function<bool(std::string)> ); // #2
int main()
{
// error: unresolved overloaded function type
// invok(test);
// still error: no known conversion from std::string to
// int or Widget
invok([](auto&& x) {
return test(std::forward<decltype(x)>(x));
});
}
That example has been copied from a C++ proposal.
The compiler didn't choose #2. It's trying to decide if it can choose #2.
To do that, it asks "can this generic lambda be converted to
std::function<bool(std::string)>
"?std::function
's converting constructor says "only if it's callable with astd::string
rvalue and the result type is convertible tobool
".Compiler tries that, deduce
auto
asstd::string
, substitute into the signature of the function call operator...success! Oops, the return type isauto
, and it needs an actual type to answer the "is convertible" question. So it instantiates the body of the function call operator template to figure out the return type.Ouch. The body isn't valid for
std::string
after all. Hard error and explosions follow.