编译器无法推导出模板函数的类型?

Edu*_*yan 5 c++ templates type-deduction c++17

我有以下代码示例:

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);
}
Run Code Online (Sandbox Code Playgroud)

这里编译器错误地显示以下消息:

could not deduce template argument for 'F'
Run Code Online (Sandbox Code Playgroud)

显式traverse(M, print<std::string>);解决了问题。
我的问题真的是为什么编译器不能推断出打印函数的模板类型?

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

Nic*_*las 5

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

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

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