c ++中的:: operator规则

11 c++ language-lawyer

我认为::在访问全局范围的情况下,运算符可以是一元的.在所有其他情况下,::将被视为二元运算符,并且对于::运算符的求值规则N1::N2::N3::n等效于以下内容:

((N1::N2)::N3)::n // Error: ::n has not been declared
Run Code Online (Sandbox Code Playgroud)

但那条线不能编译.这很好奇.标准中没有关于评估的任何信息nested-name-specifier.如果评估nested-name-specified相当于qualified/unqualified-id,但在标准中的任何地方都没有这样说,那将是很自然的.那么我们可以假设a的评估nested-name-specifier是依赖于实现的吗?

Dan*_*vil 9

[expr.prim.general](5.1.1/8-9)::中列出了解析规则.它要求::后跟名称空间/类的名称或名称空间/类的成员名称.(并且)不被允许.

更具体地在[over.oper](13.5/1)的标准定义operator-function-idoperator为一体new,delete,+,-,!,=,ˆ=,&=,<=,>=,(),[],new[],*,<,|=,&&,delete[],/,>,<<,||,%,+=,>>,++,ˆ,-=,>>=,--,&,*=,<<=,,,|,/=,==,->*,?,%=,!=,->.

.,.*,::,?:被命名为第9条不作为普通的一元或者二元运算符的异常.


eca*_*mur 8

范围解析运算符::是右关联的,因为嵌套名称说明符生成的递归语法是右关联的:

nested-name-specifier:
    ::[opt] type-name ::
    ::[opt] namespace-name ::
    decltype-specifier ::
    nested-name-specifier identifier ::
    nested-name-specifier template[opt] simple-template-id ::
Run Code Online (Sandbox Code Playgroud)

用于递归计算嵌套名称说明符的适当规则是3.4.3 [basic.lookup.qual]:

1 - 在将::范围解析运算符(5.1)应用于表示其类,命名空间或枚举的嵌套名称说明符之后,可以引用类或命名空间成员或枚举数的名称.[...]

重要的是,与仅讨论限定id的查找的5.1 (在5.1.1p8中)不同,3.4.3p1是不受限制的,因此可以用于递归地查找嵌套名称说明符.

那就是:

namespace A {
    namespace B {
        struct C {
            struct D {
                static int i;
            };
        };
    }
}
A::B::C::D::i;
Run Code Online (Sandbox Code Playgroud)

A::B::C::D::i被解析为一个合格-ID包含递归嵌套名称说明符小号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 s(7.1.3),namespace-name s(7.3)和class-name s(9.1)),只要语法允许在讨论的上下文中使用这些名称按照特定的规则.[...]

A现在的查找根据应用于特定上下文的3.4.1 [basic.lookup.unqual]的规则进行.由于我们处于全球范围,因此3.4.1p4适用,我们搜索全球范围的名称A.我们找到命名空间A,并相应地评估A::B::C::D::i收益.


也就是说,嵌套名称说明符中最左边(最里面)的名称被查找为非限定名称; 连续的名称在其内部嵌套名称说明符中被查找为限定名称.