I'm trying to use a function pointer with template as an argument. But the compiler seems to have trouble handling lambda and nullptr.
Everything is fine when I change void (*callback)(T input)
to void (*callback)(int input)
in the following code.
Is this compiler behavior specified by the C++ standard?
The compile command I use is $ g++ main.cpp -std=c+11
but the same behavior found in Visual Studio 2019.
template <class T>
int dummy (T tmp, void (*callback)(T input)) {
// Doesn't do anything, just trying to compile
// If I change (T input) to (int input), it compiles fine
if (callback)
return 1;
else
return 0;
}
void callback (int input) {
return;
}
int main () {
int tmp = 10;
auto callback_lambda = [](int input) -> void {
return;
};
dummy(tmp, callback); // Compiles OK
dummy(tmp, callback_lambda); // Error: mismatched types 'void (*)(T)' and 'main()::<lambda(<int>)'
dummy(tmp, nullptr); // Error: no matching function for call to 'dummy(int&, std:nullptr_t)'
return 0;
}
The problem is that implicit conversion won't be considered in template argument deduction.
Type deduction does not consider implicit conversions (other than type adjustments listed above): that's the job for overload resolution, which happens later.
So when passing lambda and nullptr
, the conversions to the function pointer aren't considered, the template parameter T
can't be deduced for the 2nd function argument and then cause the error.
You can make the 2nd function parameter to non-deduced context, to exclude it from deduction, with the help of std::type_identity
.
type_identity
can be used to block template argument deduction:
e.g.
template <class T>
int dummy (T tmp, void (*callback)(std::type_identity_t<T>)) {
...
}
LIVE
PS: If your compiler doesn't support std::type_identity
(since C++20), you can define your own version, it's not difficult.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With