c – 应用非限定名称查找而不是依赖于参数的名称查找

考虑标准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)不是函数调用?我想知道我们什么时候没有像先前声明的typedef int f那样的错误;如下例所示:

#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中提供).

3.4.1 / 3明确指出,为了解析的目的,为了执行是否是后缀表达式或函数调用的初始确定,执行通常的名称查找. “常用”表示按3.4.1的其余部分所述执行查找,并且在该初始阶段不使用ADL. 3.4.1 / 3明确指出“3.4.2中的规则对表达式的句法解释没有影响.” (3.4.2是ADL).

在此示例中,在解析f(a)时,通常使用查找来查找名称f.它找到全局typedef-name :: f而不是其他内容.这意味着f(a)被视为后缀表达式(强制转换),而不是函数调用.注意,在A中的函数f的朋友声明引用函数N :: f,但是它没有向N引入N :: f的声明.因为N :: f函数没有在N中显式声明(它是不可见的在N)中,通常的查找不会看到它.它只能看到global :: f,它是一个typedef-name.

如果您希望通常的名称查找在第一个示例中找到该函数,则必须明确地在N中声明该函数

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)视为函数调用.

你的第二个例子与第一个例子有很大不同.你没有额外的命名空间.因此,B中的友元函数声明引用了全局:: foo并声称foo是一个函数.但是global :: foo已经被声明为typedef-name.这种矛盾恰恰是导致错误的原因.

(有趣的是,标准的C 03版本包含3.4.1 / 3中的一个例子,这基本上等同于你的第二个例子.即标准中的例子是不正确的.这被报告为标准的Defect #139.)

上一篇:利用python实现微信小项目


下一篇:第一个微信小项目