以下代码是我正在经历的cpp测验的一部分:
#include <iostream>
template<typename T>
void foo(T)
{
std::cout << "T" << std::endl;;
}
struct S
{
};
template<typename T>
void call_foo(T t)
{
foo(S());
foo(t);
}
void foo(S)
{
std::cout << "S" << std::endl;
}
int main()
{
call_foo(S());
}
我无法理解为什么输出结果为TS
。我预计它会SS
编译器:gcc版本4.8.5 20150623
答案 0 :(得分:4)
§14.6¶9陈述:“当寻找a中使用的名称的声明时 模板定义,使用通常的查找规则(§3.4.1,§3.4.2) 对于非依赖名称。查找依赖于模板的名称 参数被推迟,直到知道实际模板参数 (§14.6.2)。“
对foo的第一次调用是非依赖调用,因此在定义函数模板时会查找它。在第二次调用的情况下,它被推迟到模板被实例化,因为它取决于模板参数。
template<typename T> void call_foo_function(T t)
{
foo(S()); // Independent, looks up foo now.
foo(t); // Dependent, looks up foo later.
}
在定义函数模板时查找foo时,唯一存在的foo版本是模板化的foo(T)。具体来说,foo(S)尚不存在,也不是候选者。
有趣的是检查你的代码在Visual Studio中输出的内容,我认为在这种情况下它会输出你期望的SS
。
答案来源:CPPQuiz。
不幸的是,由于我无法再找到答案,因此我没有答案的确切链接。
答案 1 :(得分:3)
您期望通过参数依赖查找以相同方式解析两个调用。但在这种情况下:
foo(S());
foo(t);
第一个foo
不是从属名称。回想一下,模板中函数的名称查找有两种方式:
因为第一次调用不依赖,所以只进行常规的非限定名称查找。此时,唯一可见的重载是您之前定义的函数模板foo
。第二个重载尚未可用,因此未调用。