为什么gcc、clang、msvc能成功编译以下代码? (神箭)
namespace impl {
class A;
} // namespace impl
namespace api {
using namespace impl;
} // namespace api
class B
{
friend class api::A; // (1)
};
在我看来,这种特殊类型的友元声明需要详细类型说明符。详细类型说明符是
class
关键字,后跟类名。但是这个翻译单元中没有名为 api::A
的类。 using-directive 不声明此类,它仅影响名称查找规则。因此,我预计标记为 (1)
的行的编译会失败,并出现错误,即命名空间 class
中没有 api
A。但主要编译器接受它......我错过了什么?
还有后续问题:如果我将 using-directive
using namespace impl;
替换为 using-declaration using impl::A;
,那么真的会在命名空间 A
中声明名称 api
,从而使代码格式良好?
为了了解发生了什么,我们必须查看代码的每个元素:
namespace impl {
class A;
};
是一个声明
namespace
的 class A
。
namespace api {
using namespace impl;
};
是一个使用
namespace
的 namespace impl
,其中声明了 class A
。
class B
{
friend class api::A; // (1)
};
是一个具有声明的
class
,它告诉编译器,class A
位于使用namespace api
的namespace impl
中,是friend
的class B
。
它本质上是一条链条。
B::api
-> api::impl
-> impl::A
。