带有模板的 C++ 函数指针参数
C++ function pointer argument with template
我正在尝试使用带有模板的函数指针作为参数。但是编译器似乎无法处理 lambda 和 nullptr。
当我在下面的代码中将 void (*callback)(T input)
更改为 void (*callback)(int input)
时一切正常。
此编译器行为是否由 C++ 标准指定?
我使用的编译命令是 $ g++ main.cpp -std=c+11
,但在 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;
}
问题是在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.
所以在传递lambda和nullptr
时,没有考虑到函数指针的转换,模板参数T
不能推导出第二个函数参数,然后导致错误.
您可以将第二个函数参数设为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:
例如
template <class T>
int dummy (T tmp, void (*callback)(std::type_identity_t<T>)) {
...
}
PS:如果你的编译器不支持std::type_identity
(C++20 起),你可以定义你自己的版本,这并不困难。
我正在尝试使用带有模板的函数指针作为参数。但是编译器似乎无法处理 lambda 和 nullptr。
当我在下面的代码中将 void (*callback)(T input)
更改为 void (*callback)(int input)
时一切正常。
此编译器行为是否由 C++ 标准指定?
我使用的编译命令是 $ g++ main.cpp -std=c+11
,但在 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;
}
问题是在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.
所以在传递lambda和nullptr
时,没有考虑到函数指针的转换,模板参数T
不能推导出第二个函数参数,然后导致错误.
您可以将第二个函数参数设为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:
例如
template <class T>
int dummy (T tmp, void (*callback)(std::type_identity_t<T>)) {
...
}
PS:如果你的编译器不支持std::type_identity
(C++20 起),你可以定义你自己的版本,这并不困难。