这段代码应该如何表现?如果我在 call_read()
函数中使用 qualified 名称,它会调用通用函数而忽略我的重载;如果我使用 unqualified 名称,它首先调用重载,然后调用通用版本。有什么不同?它是 GCC 中的错误吗?
#include <iostream>
struct info1 {};
struct info2 {};
template<class T> void read(T& x)
{
std::cout << "generic" << std::endl;
}
template<class T> void call_read(T& x)
{
::read(x); // if I replace ::read(x) with read(x) the overload is called
}
void read(info1& x)
{
std::cout << "overload" << std::endl;
}
int main()
{
info1 x;
info2 y;
call_read(x);
call_read(y);
}
我还注意到它对基本类型的工作方式不同。 请看下面的代码
#include <iostream>
typedef struct info1 {};
typedef struct info2 {};
typedef int info3;
typedef double info4;
template<class T> void read(T x)
{
std::cout << "generic" << std::endl;
}
template<class T> void call_read(T x)
{
read(x);
}
void read(info1 x)
{
std::cout << "overload" << std::endl;
}
void read(info3 x)
{
std::cout << "overload" << std::endl;
}
int main()
{
call_read(info1());
call_read(info2());
call_read(info3());
call_read(info4());
}
它应该调用两次重载函数,但事实并非如此。 在这里查看结果 http://codepad.org/iFOOFD52
最佳答案
您所观察的是两阶段名称查找和参数相关查找的叠加。
让我们看看标准是怎么说的 (C++03)。 [temp.dep]:
[...] In an expression of the form:
postfix-expression ( expression-listopt )
where the postfix-expression is an identifier, the identifier denotes a dependent name if and only if any of the expressions in the expression-list is a type-dependent expression (14.6.2.2).
这意味着在 read
和 ::read
中,read
都是从属名称,因为 x
是类型相关。这意味着它在实例化时已解决。让我们看看这个[temp.dep.candidate]的规则是什么:
For a function call that depends on a template parameter, if the function name is an unqualified-id but not a template-id, the candidate functions are found using the usual lookup rules (3.4.1, 3.4.2) except that:
— For the part of the lookup using unqualified name lookup (3.4.1), only function declarations with external linkage from the template definition context are found.
因此对于 ::read
情况,只考虑在模板定义之前声明的函数。但是:
— For the part of the lookup using associated namespaces (3.4.2), only function declarations with external linkage found in either the template definition context or the template instantiation context are found.
对于不合格的read
,两个函数都被考虑,在模板定义和模板实例化时可见。
关于c++ - 模板的合格和不合格名称查找的不同行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8501294/