C++ c+中的::运算符的规则+;
我认为C++ c+中的::运算符的规则+;,c++,language-lawyer,C++,Language Lawyer,我认为::操作符在访问全局范围时可以是一元的。在所有其他情况下,::被视为二进制运算符,在N1::N2::N3::n情况下,:运算符的求值规则等效于以下内容: ((N1::N2)::N3)::n // Error: ::n has not been declared 但这行代码无法编译。这很奇怪。标准中没有任何关于嵌套名称说明符评估的信息。如果指定的嵌套名称的求值等同于合格/不合格id,这将是很自然的,但是它在标准中的任何地方都没有这样说。那么我们可以假设嵌套名称说明符的计算依赖于实现吗?没有
::
操作符在访问全局范围时可以是一元的。在所有其他情况下,::
被视为二进制运算符,在N1::N2::N3::n
情况下,:
运算符的求值规则等效于以下内容:
((N1::N2)::N3)::n // Error: ::n has not been declared
但这行代码无法编译。这很奇怪。标准中没有任何关于
嵌套名称说明符
评估的信息。如果指定的嵌套名称的求值等同于合格/不合格id
,这将是很自然的,但是它在标准中的任何地方都没有这样说。那么我们可以假设嵌套名称说明符的计算依赖于实现吗?没有任何依赖于实现的内容。但是,您错误地假设它是一个操作员。不是。因此,它既不是一元运算符,也不是二元运算符,并且不形成表达式。由于它不构成表达式,因此没有对这些表达式的求值。在[expr.prim.general]
(5.1.1/8-9)中列出了::
的解析规则。它要求::
后跟名称空间/类的名称或名称空间/类的成员的名称<不允许使用代码>(
和)
更具体地说,在[over.oper]
(13.5/1)中,该标准将操作员功能id
和操作员
定义为新建
,删除
,+
,-
,
,=
,=
,,=
,()
,[]
,新的[]
,
,
,+
,,-
,,-
,,,,,,
,*
,::
,?:
在第9条中被命名为例外,不作为普通的一元运算符或二元运算符。范围解析运算符::
是右关联的,因为嵌套名称说明符产品的递归语法是右关联的:
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不同(5.1.1p8中只讨论合格ID的查找),3.4.3p1不受限制,因此可用于递归查找嵌套的名称说明符
即:
namespace A {
namespace B {
struct C {
struct D {
static int i;
};
};
}
}
A::B::C::D::i;
A::B::C::D::i
被解析为一个限定id,该id递归地包含嵌套的名称说明符A::B::C::D:
,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名称(7.1.3)、命名空间名称(7.3)和类名(9.1)),只要语法允许在特定规则讨论的上下文中使用此类名称。[……]
A
的查找现在按照适用于特定上下文的3.4.1[basic.lookup.unqual]规则进行。由于我们在全局范围内,因此3.4.1p4适用,我们在全局范围内搜索名称A
。我们找到了名称空间A
,对A::B::C::D::i
的评估也随之进行
也就是说,嵌套名称说明符中最左边(最里面)的名称作为非限定名称查找;连续名称在其内部嵌套名称说明符上作为限定名称进行查找。标准定义了嵌套名称说明符
,就在其定义限定id的下方。这个定义中没有括号。@Sneftel你说得对。但求值规则呢?@不,我正在寻找确定嵌套名称说明符表示的实体的后续操作?没有求值。作用域解析运算符没有优先级和关联性。表达式a::(b::c)
与(a::b)::c
相对,没有任何意义。AFAICS((N1::N2)::N3)::n
始终是一个解析错误,但例如(N1::N2)::n
将实际编译,假设存在一个类型N1::N2
和一个全局变量n
,并且n
可转换为N1::N2
!这将意味着与N1::N2::n
完全不同的事情嗯,事实并非如此。该标准调用范围解析运算符。@AndreyChernyakhovskiy So::是运算符还是不是运算符?@DmitryFucintv,这取决于您如何定义术语。该标准称之为运算符。它是一个运算符,但在编译时可以解析。@MSalters,感谢您的输入,但这是一个有争议的问题。C++'03(C++'11目前我无法使用,但我怀疑它在这一点上有所不同)的确切引语是:“以下运算符不能重载:
*
::
?:
”。也就是说,从标准的角度来看,这四个是运算符,但有一些特殊的特点:在这种情况下,关于运算符重载。如果