应用了非限定名称查找,而不是依赖于参数的名称查找 [英] Unqualified name lookup applied instead of argument-dependent name lookup
问题描述
考虑标准3.4.1/3中的示例:
Consider an example from the standard sec 3.4.1/3:
typedef int f;
namespace N
{
struct A
{
friend void f(A &);
operator int();
void g(A a)
{
int i = f(a);// f is the typedef, not the friend
// function: equivalent to int(a)
}
};
}
f(a)
是后缀表达式.编译器如何确定f(a)
不是函数调用?我想知道什么时候我们没有像f previously declared of typedef int f
这样的错误?如以下示例所示:
f(a)
is postfix expression. How does compiler determine that f(a)
is not a function call? I'm wondering when we have no error like f previously declared of typedef int f
; as in the following example:
#include <stdio.h>
typedef int foo; //error: previous declaration of ‘typedef int foo’
class B
{
public:
friend void foo(B b){ printf("3"); } //error: ‘void foo(B)’ redeclared as different kind of symbol
static const int c=42;
};
int main(){ }
推荐答案
(在我的C ++ 11文档版本中,示例见3.4.1/3).
(In my version of the C++11 document the example is presented in 3.4.1/3).
3.4.1/3明确指出,出于解析目的,为了执行 initial 判断这是后缀表达式还是函数调用,通常使用 名称查找被执行. 常规"是指按照3.4.1的其余部分所述执行查找,并且在该初始阶段不使用 ADL . 3.4.1/3明确表示"3.4.2中的规则对表达式的句法解释没有影响". (3.4.2是ADL).
The 3.4.1/3 clearly states that for the purposes of parsing, in order to perform the initial determination of whether this is a postfix expression or function call, a usual name lookup is performed. "Usual" means that the lookup is performed as described in the rest of 3.4.1 and no ADL is used at that initial stage. 3.4.1/3 explicitly says that "The rules in 3.4.2 have no effect on the syntactic interpretation of an expression." (3.4.2 is ADL).
在此示例中,在解析f(a)
时,通常使用查找来查找名称f
.它找到全局typedef-name ::f
,仅此而已.这意味着f(a)
被视为后缀表达式(强制转换),而不是函数调用.请注意,在A
内部的函数f
的朋友声明引用了函数N::f
,但是没有在N
中引入N::f
声明.由于N::f
函数未在N
中明确声明(在N
中不可见),因此常规查找不会看到它.它只会看到全局::f
,它是一个typedef名称.
In this example, while parsing f(a)
the usual lookup is used to look for name f
. It finds the global typedef-name ::f
and nothing else. This means that f(a)
is treated as a postfix expression (a cast), not as a function call. Note, that friend declaration of function f
inside A
refers to function N::f
, but it does not introduce a declaration of N::f
into N
. Since N::f
function is not explicitly declared in N
(it is not visible in N
), the usual lookup does not see it. It only sees the global ::f
, which is a typedef-name.
如果要在第一个示例中使用常规名称查找来找到函数,则必须在N
中显式声明该函数
If you want the usual name lookup to find the function in the first example, you have to declare that function in N
explicitly
typedef int f;
namespace N
{
struct A; // <- added
void f(A &); // <- added
struct A
{
friend void f(A &);
...
现在N::f
的声明在N
中可见.现在,通常的名称查找将找到N::f
并从一开始就将f(a)
视为函数调用.
Now the declaration of N::f
is visible in N
. Now the usual name lookup will find N::f
and treat that f(a)
as a function call from the very beginning.
您的第二个示例与第一个示例严重不同.您那里没有多余的名称空间.因此,B
中的好友函数声明引用了全局::foo
,并声称foo
是 function .但是全局::foo
已被声明为typedef名称.这种矛盾正是导致错误的原因.
Your second example is seriously different from the first. You have no extra namespace there. Because of that the friend function declaration in B
refers to the global ::foo
and claims that foo
is a function. But the global ::foo
is already declared as a typedef-name. This contradiction is exactly what causes the error.
(有趣的是,该标准的C ++ 03版本在3.4.1/3中包含一个示例,该示例基本上等同于您的第二个示例.即,该标准中的示例格式错误.报告为标准的缺陷#139 .)
(Amusingly, C++03 version of the standard contained an example in 3.4.1/3, which was essentially equivalent to your second example. I.e. the example in the standard was ill-formed. This is reported as Defect #139 of the standard.)
这篇关于应用了非限定名称查找,而不是依赖于参数的名称查找的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!