【发布时间】:2018-11-15 18:57:25
【问题描述】:
在探索 C++ 中的模板时,我偶然发现了以下代码中的示例:
#include <iostream>
#include <functional>
template <typename T>
void call(std::function<void(T)> f, T v)
{
f(v);
}
int main(int argc, char const *argv[])
{
auto foo = [](int i) {
std::cout << i << std::endl;
};
call(foo, 1);
return 0;
}
为了编译这个程序,我使用 GNU C++ 编译器 g++:
$ g++ --version // g++ (Ubuntu 6.5.0-1ubuntu1~16.04) 6.5.0 20181026
为C++11编译后,出现如下错误:
$ g++ -std=c++11 template_example_1.cpp -Wall
template_example_1.cpp: In function ‘int main(int, const char**)’:
template_example_1.cpp:15:16: error: no matching function for call to ‘call(main(int, const char**)::<lambda(int)>&, int)’
call(foo, 1);
^
template_example_1.cpp:5:6: note: candidate: template<class T> void call(std::function<void(T)>, T)
void call(std::function<void(T)> f, T v)
^~~~
template_example_1.cpp:5:6: note: template argument deduction/substitution failed:
template_example_1.cpp:15:16: note: ‘main(int, const char**)::<lambda(int)>’ is not derived from ‘std::function<void(T)>’
call(foo, 1);
^
(C++14 和 C++17 相同)
根据编译器错误和注释,我了解到编译器无法推断出 lambda 的类型,因为它无法与 std::function 匹配。
查看之前有关此错误的问题(1、2、3 和4),我仍然对此感到困惑。
正如问题 3 和 4 的答案中所指出的,可以通过显式指定模板参数来修复此错误,如下所示:
int main(int argc, char const *argv[])
{
...
call<int>(foo, 1); // <-- specify template argument type
// call<double>(foo, 1) // <-- works! Why?
return 0;
}
但是,当我使用其他类型而不是 int 时,例如 double、float、char 或 bool,它也能正常工作,这让我更加困惑。
所以,我的问题如下:
- 为什么当我明确指定
int(和其他)作为模板参数时它会起作用? - 有没有更通用的方法来解决这个问题?
【问题讨论】:
-
为什么是
std::function?为什么不只是T f? -
@tkausl 和
T f,我将无法将f用作函数。 -
@omar tkausl 可能是指
F f。
标签: c++ c++11 templates lambda c++17