Why does the following code not compile?
Why do I have to tell the compiler that the passed function pointer returns a double? (It works if one explicitly calls call<double>()
!)
template<typename T>
void call(T (*const _pF)(void))
{
}
int main(int, char**)
{ call(
[](void) -> double
{ return 1.0;
}
);
}
CodePudding user response:
Because the implicit conversion (from lambda to function pointer) won't be considered in template argument deduction, the template parameter T
can't be deduced and the invocation fails.
Type deduction does not consider implicit conversions (other than type adjustments listed above): that's the job for overload resolution, which happens later.
Except for specifying template argument double
explicitly like call<double>(...);
, you can convert the lambda to function pointer explicitly, e.g.
call(
static_cast<double(*)()>(
[](void) -> double
{ return 1.0;
})
);
or
call(
[](void) -> double
{ return 1.0;
}
);
CodePudding user response:
You did not pass the lambda to your call
function but implicitly create a function pointer of it. That makes your call function only works with captureless lambdas. If that is ok, fine!
But you can simplify all the stuff by accepting the lambda type itself!
template<typename T>
auto call(T &&f)
{
return f();
}
int main(int, char**)
{
std::cout << call( [](){ return 1.0; } ) << std::endl;
}
There is also no need to specify the return value of the lambda as 1.0
automatically makes the return type of the lambda a double
.
As you can see, also the return type of call
can be deduced and as the result you can directly use the call function to return the result itself to something.
But all this has also a drawback: For each lambda you get a new template instance of call.