作用域解析运算符
::
是右关联的,这是因为嵌套名称指定符的递归语法是右关联的:
nested-name-specifier:
::[opt] type-name ::
::[opt] namespace-name ::
decltype-specifier ::
nested-name-specifier identifier ::
nested-name-specifier template[opt] simple-template-id ::
递归评估嵌套名称限定符的适当规则是3.4.3 [basic.lookup.qual]:
1-可将类或命名空间成员或枚举器的名称在双冒号作用域解析运算符(5.1)应用于表示其类、命名空间或枚举器的嵌套名称限定符之后引用。[...]
重要的是,与5.1不同,后者仅讨论限定ID的查找(在5.1.1p8中),3.4.3p1没有限制,因此可以用于递归查找嵌套名称限定符。
也就是说,在以下代码中:
namespace A {
namespace B {
struct C {
struct D {
static int i;
};
};
}
}
A::B::C::D::i;
A::B::C::D::i
被解析为一个限定名(qualified-id),其中包含递归的嵌套名字指示符(nested-name-specifier) A::B::C::D::
、A::B::C::
、A::B::
和A::
。现在,要评估A::B::C::D::i
:
- 我们使用5.1.1p8,需要评估
A::B::C::D
;
- 我们使用3.4.3p1,需要评估
A::B::C
;
- 我们使用3.4.3p1,需要评估
A::B
;
- 我们使用3.4.3p1,需要评估
A
。
现在我们必须找到一个A
“表示”一个“类、命名空间或枚举”的意义。在没有更具体的内容的情况下,第3节将我们转到3.4节:
1- 名称查找规则统一适用于所有名称(包括typedef-name(7.1.3)、namespace-name(7.3)和class-name(9.1)),无论语法规则允许在特定规则讨论的上下文中使用这些名称。[...]
A
的查找现在按照3.4.1 [basic.lookup.unqual]的规则在特定上下文中进行。由于我们在全局作用域中,应用3.4.1p4,我们在全局作用域中搜索名称A
。我们找到命名空间A
,并相应地继续评估A::B::C::D::i
。
也就是说,嵌套名字指示符(nested-name-specifier)中的最左边(内部)名称被视为未限定名称进行查找;���下来的名称将根据其内部的嵌套名字指示符(nested-name-specifier)作为限定名称进行查找。
a::(b::c)
与(a::b)::c
相对无意义,a::(b + c)
也是如此。 - ach((N1::N2)::N3)::n
总是一个语法错误,但例如(N1::N2)::n
如果存在类型N1::N2
和全局变量n
,并且n
可以转换为N1::N2
,那么它实际上可以编译通过!这只是意味着与N1::N2::n
完全不同的事情。 :) - JohannesD