C++ 为什么这个模板推理失败

C++ 为什么这个模板推理失败,c++,templates,c++11,template-argument-deduction,C++,Templates,C++11,Template Argument Deduction,此代码不会使用clang++6.0或g++4.9.1编译(代码没有任何意义,但这是实现此功能的最低示例): 我不明白为什么编译器不能推断模板参数,奇怪的是编译器对foo()您试图从非推断上下文§[temp.decreate.type]/5推断模板参数非常满意 非推断上下文为: -使用限定id指定的类型的嵌套名称说明符 i、 e 模板 T getItem(typename std::forward_list::const_iterator it) ^^^^^^^^^^^^^^^^^^^^ 和§[

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


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

您试图从非推断上下文§[temp.decreate.type]/5推断模板参数非常满意

非推断上下文为:

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

i、 e

模板
T getItem(typename std::forward_list::const_iterator it)
^^^^^^^^^^^^^^^^^^^^
和§[临时扣除类型]/4

但是,在某些上下文中,该值不参与类型推断,而是使用在别处推导或显式指定的模板参数的值如果模板参数仅在非推断上下文中使用且未明确指定,则模板参数推断将失败。


如果您尝试实例化
foo
。使用上面的代码,
foo
不会出现错误,因为依赖名称只在实例化时查找(这通常称为两阶段查找)。美国联邦法规

您可以自己“推断”参数:
template auto getItem(T it)->decltype(*it){return*it;}
。不是很好的主意,但它很有效)自动项=*list.begin()有什么问题
#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.
template<typename T>
void bar(const std::forward_list<T>& list) {
    auto item = getItem<T>(list.cbegin());
}
template<typename T>
T getItem(typename std::forward_list<T>::const_iterator it)
                   ^^^^^^^^^^^^^^^^^^^^