应用了非限定名称查找,而不是依赖于参数的名称查找 [英] Unqualified name lookup applied instead of argument-dependent name lookup

查看:70
本文介绍了应用了非限定名称查找,而不是依赖于参数的名称查找的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

考虑标准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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆