首页 > 解决方案 > 编译器无法推断模板函数的类型?

问题描述

我有以下代码示例:

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>);解决了问题。
我的问题真的是为什么编译器不能推断打印函数的模板类型?

据我了解,所有编译时间信息都是可用的。

标签: c++templatesc++17type-deduction

解决方案


模板参数推导基于函数的模板参数、函数的签名和提供的参数类型。而已。即使忽略作为模板函数的事实print(因此没有可用于推导的类型),签名中也没有任何内容traverse可以让编译器知道要推导的类型将是print<std::string>. 任何此类信息都将在函数的定义中。

traverse尚不存在且在实例化之前无法存在的定义。在您拥有模板参数之前,您无法实例化模板。这就是模板参数推导的目的。

此外,如前所述,print它不是函数;它是模板的名称。它没有类型;它甚至不是一个函数。它是一种基于模板参数生成函数的方法。即使您尝试传递print给不是模板的函数,代码仍然无法工作。编译器只能在调用函数时对函数执行模板参数推导,而不是在将它们作为函数参数传递时。在所有非推导的情况下,您必须直接提供模板参数。


推荐阅读