c++ - 编译器无法推断模板函数的类型?
问题描述
我有以下代码示例:
template<typename T>
void print(T t) {
std::cout << t << std::endl;
}
template<typename Key, typename Value, typename F>
void traverse(std::map<Key, Value>& m, F f) {
for (auto&& [key, value] : m) {
f(value);
}
}
int main()
{
std::map<int, std::string> M;
// initializing the map
traverse(M, print);
}
在这里,编译器出错并显示以下消息:
could not deduce template argument for 'F'
显式traverse(M, print<std::string>);
解决了问题。
我的问题真的是为什么编译器不能推断打印函数的模板类型?
据我了解,所有编译时间信息都是可用的。
解决方案
模板参数推导基于函数的模板参数、函数的签名和提供的参数类型。而已。即使忽略作为模板函数的事实print
(因此没有可用于推导的类型),签名中也没有任何内容traverse
可以让编译器知道要推导的类型将是print<std::string>
. 任何此类信息都将在函数的定义中。
traverse
尚不存在且在实例化之前无法存在的定义。在您拥有模板参数之前,您无法实例化模板。这就是模板参数推导的目的。
此外,如前所述,print
它不是函数;它是模板的名称。它没有类型;它甚至不是一个函数。它是一种基于模板参数生成函数的方法。即使您尝试传递print
给不是模板的函数,代码仍然无法工作。编译器只能在调用函数时对函数执行模板参数推导,而不是在将它们作为函数参数传递时。在所有非推导的情况下,您必须直接提供模板参数。
推荐阅读
- python - 获取 KeyError: '' with request url
- windows-10 - 使用任务计划程序唤醒后,Windows 10 电脑在两分钟内重新进入睡眠状态
- reactjs - 在 React 中添加新项目后,本地状态被重置
- docker - 如何在超级账本结构上运行 trade.sh 脚本?
- ios - 如何使用 StoreKit 2 进行还原?
- openstack - 如果在启用提供者网络之前创建了提供者网络,则提供者网络不起作用
- javascript - 带有多个元素的Jquery可拖动ui可以恢复到原始位置?
- r - 如何使用 R 将变量内的 json 格式的数据转换为我的数据集中的新列
- oracle - 每行只显示一列,Sqlplus
- python - 仅更改 python 代码中的运算符