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目前我无法使用,但我怀疑它在这一点上有所不同)的确切引语是:“以下运算符不能重载:
*
::
?:
”。也就是说,从标准的角度来看,这四个是运算符,但有一些特殊的特点:在这种情况下,关于运算符重载。如果