为什么此模板推理失败

Why is this template inference failing

本文关键字:推理 失败 为什么      更新时间:2023-10-16

这段代码不会用clang++6.0或g++4.9.1编译(代码没有任何意义,但这是实现它的最小示例):

#include <forward_list>
template<typename T>
T getItem(typename std::forward_list<T>::const_iterator it) {
    return *it;
}
template<typename T>
void foo() {
    std::forward_list<T> list;
    auto item = getItem(list.cbegin());
}
template<typename T>
void bar(const std::forward_list<T>& list) {
    auto item = getItem(list.cbegin());
}
int main() {
    std::forward_list<int> list;
    bar(list);
}

我收到这个错误

t2.cpp:17:17: error: no matching function for call to 'getItem'
    auto item = getItem(list.cbegin());
                ^~~~~~~
t2.cpp:22:5: note: in instantiation of function template specialization 'bar<int>' requested here
    bar(list);
    ^
t2.cpp:4:3: note: candidate template ignored: couldn't infer template argument 'T'
T getItem(typename std::forward_list<T>::const_iterator it) {
  ^
1 error generated.

要修复它,我需要更改bar()的调用,如下所示:

template<typename T>
void bar(const std::forward_list<T>& list) {
    auto item = getItem<T>(list.cbegin());
}

我不明白为什么编译器不能推断模板参数,奇怪的是编译器对foo()非常满意。

您正试图从一个未推导的上下文中推导出一个模板参数,§[temp.decure.type]/5

未推导的上下文为:

--使用限定id指定的类型的嵌套名称说明符。

template<typename T>
T getItem(typename std::forward_list<T>::const_iterator it)
                   ^^^^^^^^^^^^^^^^^^^^

§[临时扣除类型]/4

然而,在某些上下文中,该值不参与类型推导,而是使用在其他地方推导或明确指定的模板参数的值如果模板参数仅在非推导上下文中使用,并且未明确指定,则模板参数推导失败

如果您尝试实例化foo,它将给出相同的错误。使用上面的代码,foo不会出现错误,因为依赖名称只在实例化时查找(这通常被称为两阶段查找)。参考。非实例化C++模板函数的语义正确性