成员函数Outer :: f()不是类Outer :: Inner的朋友.为什么?

Bel*_*loc 12 c++ friend language-lawyer c++14

,gcc和vs2013,功能Outer::f不是类的朋友Outer::Inner.

struct Outer {
    void f() {}
    class Inner {
        friend void f();
        static const int i = 0;
    };
};

void f() { int i = Outer::Inner::i; }
Run Code Online (Sandbox Code Playgroud)

从[namespace.memdef]/3我希望函数Outer::f成为朋友Outer::Inner,而不是::f因为友元声明不是包含名称的名称空间中的第一个f.

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

首先在名称空间中声明的每个名称都是该名称空间的成员.如果非本地类中的朋友声明首先 声明了类,函数,类模板或函数模板97,则该朋友是最内部封闭命名空间的成员.友元声明本身不会使名称对非限定查找(3.4.1)或限定查找(3.4.3)可见.[注意:如果在命名空间范围内提供匹配的声明(在类定义授予友谊之前或之后),则朋友的名称将在其命名空间中可见. - 结束注释]如果调用了友元函数或函数模板,则可以通过名称查找找到其名称,该名称查找考虑名称空间中的函数和与函数参数类型相关联的类(3.4.2).如果友元声明中的名称既不是限定语句也不是模板标识,并且声明是函数或详细类型说明符,则确定实体是否先前已声明的查找不应考虑最内层封闭命名空间之外的任何范围.

R S*_*ahu 9

你引用的标准的第一部分说(强调我的):

首先在名称空间中声明的每个名称都是该名称空间的成员.如果非本地类中的友元声明首先声明一个类或函数,那么友元类或函数是最内层封闭命名空间的成员.

您假设某个类与命名空间相同,这是不正确的.

namespace Outer {
    void f();
    class Inner {
        friend void f();
        static const int i = 0;
    };
}

void Outer::f() { int i = Outer::Inner::i; }
Run Code Online (Sandbox Code Playgroud)

应该管用.要使用类成员函数作为朋友,您必须使用:

struct Outer {
    void f();
    class Inner {
        friend void Outer::f();
        static const int i = 0;
    };
};

void Outer::f() { int i = Outer::Inner::i; }
Run Code Online (Sandbox Code Playgroud)