问题描述
此代码应如何运行?如果在 call_read()
函数中使用限定名称,则调用忽略我的重载的泛型函数;如果我使用非限定名称,它会先调用重载,然后调用通用版本。有什么不同?这是GCC中的错误吗?
How should this code behave? It calls generic function ignoring my overload if I use qualified name in call_read()
function; and it calls overload first and then generic version if I use unqualified name. What's the difference? Is it a bug in 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);
}
我还注意到它对基本类型的工作不同。
查看下面的代码
I also noticed that it works different for fundamental types.See the code bellow
#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());
}
它应该调用重载函数两次,但不是。
查看结果
It is supposed to call overloaded function twice, but it's not.See the result herehttp://codepad.org/iFOOFD52
推荐答案
您观察到的是两相名称查找和 / em>。
What you're observing is a superposition of two-phase name lookup and argument dependent lookup.
让我们看看标准说的是什么(C ++ 03)。 [temp.dep]:
Let's see what the standard says (C++03). [temp.dep]:
postfix-expression ( expression-listopt )
其中postfix-expression是标识符,当且仅当表达式列表中的任何表达式是类型依赖表达式(14.6.2.2)时,标识符表示依赖名称。
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
是一个依赖名称,因为 x
是类型相关的。这意味着它在实例化的时候解决。让我们看看这个[temp.dep.candidate]的规则是什么:
That means that in both read
and ::read
, read
is a dependent name because x
is type-dependent. That means that it's resolved at the point of instantiation. Let's see what are the rules for this [temp.dep.candidate]:
- 对于使用非限定名称查找(3.4.1)的查找部分,仅找到具有模板定义上下文的外部链接的函数声明。
— 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
情况,只考虑在模板定义之前声明的函数。但是:
Therefore for the ::read
case only functions declared before the template definition are considered. But:
用于不合格的 read
两个函数,它们在模板定义和模板实例化时可见。
for the unqualified read
both functions are considered, those visible at template definition and template instantiation.
这篇关于针对模板的有限和无限定名称查找的不同行为的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!