friend类声明和using指令

Mit*_*iya 13 c++ namespaces using-directives friend name-lookup

以下示例是否格式正确?

namespace N {
    class A;
}
using namespace N;

class B {
    int i;
    friend class A;
};

namespace N {
    class A {
        B m;
        int get() { return m.i; }
    };
}
Run Code Online (Sandbox Code Playgroud)

这个例子使用Clang 3.5成功编译,但是使用g ++ 4.8.1失败了以下内容:

main.cpp: In member function ‘int N::A::get()’:
main.cpp:7:9: error: ‘int B::i’ is private
     int i;
         ^
main.cpp:14:30: error: within this context
         int get() { return m.i; }
                              ^
Run Code Online (Sandbox Code Playgroud)

C++ 11标准§7.3.1.2p3说,

如果friend声明中的名称既不是限定名也不是模板标识,并且声明是函数或详细类型说明符,则确定实体是否先前已声明的查找不应考虑最内层封闭命名空间之外的任何范围.

例如,class A不是最内层封闭命名空间(即全局命名空间)的成员,而是class A通过using指令引入全局命名空间.

Die*_*ühl 8

为了让N::A没有资质friendB,你会使用

friend A;
Run Code Online (Sandbox Code Playgroud)

而不是

friend class A;
Run Code Online (Sandbox Code Playgroud)

当使用精心设计的类型说明符,即,class A它是这种特定的形式时,它引入了一个类名(见3.4.4 [basic.lookup.elab]第2段).


小智 1

虽然使用命名空间 N 将名称 N::A 拉入全局命名空间,但它并未在全局命名空间中声明 A。因此,全局名称空间中的附加 A 是 B 的友元。 clang 是错误的。