我有以下代码,无法编译
template <typename T>
void call_with(std::function<void(T)> f, T val) {
f(val);
}
int main() {
auto print = [](int x) { std::cout << x; };
call_with(print, 42);
}
编译错误看起来像这样
tst.cpp:17:2: error: no matching function for call to 'call_with'
call_with(print, 42);
^~~~~~~~~
tst.cpp:11:6: note: candidate template ignored: could not match 'function<void (type-parameter-0-0)>' against
'(lambda at tst.cpp:16:15)'
void call_with(std::function<void(T)> f, T val) {
^
1 error generated
我尝试用 g++ tst.cpp -o tst -std=c++17
编译它
所以我知道有时 C++ 可以在某些条件下推导出模板参数,但我想知道为什么在这种情况下它无法编译此代码。看起来类型 T
不能有任何其他选项可以是任何东西,但 int 和 f
绝不是 std::function<void(int)>
.
最佳答案
因为print
不是std::function<void(int)>
.并且它可以转换为多个有效类型。
尝试运行
auto print = [](int x) { std::cout << x; };
std::cout << typeid(print).name()<<"\n";
std::function<void(unsigned __int64)> print_a = std::function<void(unsigned __int64)>(print);
std::cout << typeid(print_a).name() << "\n";
auto print_b = std::function<void(unsigned __int64)>(print);
std::cout << typeid(print_b).name() << "\n";
你将会得到
class <lambda_d103cbf184cf5bdcf1494399ee6d564a>
class std::function<void __cdecl(unsigned __int64)>
class std::function<void __cdecl(unsigned __int64)>
这显示 print
是 lambda
,并且可以转换为多种std::function<void(T)>
像:
auto print = [](int x) { std::cout << x; };
auto print2 = std::function<void(unsigned __int64)>(print);
auto print3 = std::function<void(unsigned short)>(print);
auto print4 = std::function<void(char)>(print);
精确的std::function<void(int)>
可以推导出对象:
std::function<void(int)> print = [](int x) { std::cout << x; };
call_with(print, 42);
并且42也需要是正确的类型才能推导
std::function<void(int)>
+ int
意味着T=int
std::function<void(short)>
+ short
意味着T=short
但是std::function<void(short)>
+ int
无法推论。
所以你会得到编译错误:
std::function<void(short)> print = [](short x) { std::cout << x; };
call_with(print, 42);
正确的版本是
std::function<void(short)> print = [](short x) { std::cout << x; };
call_with(print, short(42));
关于c++ - 为什么 C++ 编译器无法推断 lambda 参数的类型?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65060766/