为什么确定朋友声明是否是其命名空间中的第一个声明如此重要?

时间:2018-08-12 14:35:33

标签: c++ language-lawyer

[namespace.memdef]/3(重点是我的):

  

如果非本地类中的朋友声明首先声明了一个类,   函数,类模板或函数模板 106 朋友是成员   最里面的封闭命名空间。朋友声明不   本身会使名称对不合格的查找(6.4.1)可见,或者   合格查询(6.4.3)。 [注意:朋友的名字将是   如果在以下位置提供了匹配的声明,则在其名称空间中可见   命名空间范围(在类定义授予之前或之后)   友谊)。 —尾注]如果朋友功能或功能模板是   被称为,其名称可以通过考虑以下内容的名称查找来找到   命名空间和与类型相关联的类中的函数   函数参数(6.4.2)。 如果朋友声明中的姓名是   既不是合格的也不是template-id,并且声明是一个函数   或详尽的类型说明符,以确定是否   实体已事先声明,不考虑任何范围   最内层的封闭命名空间之外。 [注意:其他形式的   朋友声明不能声明最内层成员的新成员   封闭名称空间,因此遵循通常的查找规则。 —尾注   ] [示例:...

code below可以正确执行,而不管好友声明是否是其命名空间中的第一个声明。

#include<iostream>

namespace N{
    struct A;
    void f(A&);         // If you comment out this declaration, i.e., if the
                        // friend declaration turns out to be the first
                        // declaration in namespace N, the code will still
                        // execute correctly, i.e., printing the same result
                        // below.

    struct A {
        friend void f(A& ra) { std::cout << "friend void f(A&)\n" << ra.i; }
    private:
        int i = 100;
    };
}

N::A a;
int main(){
    f(a);
}

此代码段打印出以下内容:

friend void f(A&)
100

1 个答案:

答案 0 :(得分:2)

可以找到ADL,因为您从命名空间N传递了一个参数。可以将示例更改为此:

namespace N{
    void f(int); // If you comment out this declaration, i.e., if the
                 // friend declaration turns out to be the first
                 // declaration in namespace N, the code will fail to compile.

    struct A {
        friend void f(int) { std::cout << "friend void f()\n"; }
        private:
        int i = 100;
    };
}

int main(){
    N::f(1);
}

online compiler