在探索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匹配。
正如第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
? - tkauslT f
,我将无法将f
用作函数。 - omarF f
。 - Yakk - Adam Nevraumont