C++ C++;11单个限定名称和两个连续名称之间的歧义?
下面的C++11程序是否格式错误C++ C++;11单个限定名称和两个连续名称之间的歧义?,c++,c++11,C++,C++11,下面的C++11程序是否格式错误 struct a { struct b { }; void f() {}; }; extern struct a b; struct a ::b; int main() { b.f(); } 为什么 有趣的是这一行: struct a ::b; 这是内部类a::b的前向声明吗 或者这是全局变量b的定义?相当于: struct a (::b); 结构a::b不会声明类型为a的名为b的变量,如果您是这样要求的话。它是嵌套类型a
struct a
{
struct b { };
void f() {};
};
extern struct a b;
struct a ::b;
int main()
{
b.f();
}
为什么
有趣的是这一行:
struct a ::b;
这是内部类a::b
的前向声明吗
或者这是全局变量b
的定义?相当于:
struct a (::b);
结构a::b不会声明类型为
a
的名为b
的变量,如果您是这样要求的话。它是嵌套类型a::b
的(冗余)前向声明。在C++程序中,空白并不普遍意义重大。因此,您的程序声明但从未定义名为b
的变量。这违反了一条定义规则:因此程序的格式不正确,链接器也会告诉你同样的内容。Take 2
结构a::b是结构a::b的格式良好的声明 它不是转发声明,因为结构a::b已被 定义该标准没有正式定义远期申报,但 被普遍接受的意思是在某事物之前和之后的声明 与它的定义是分开的 它也不是全局变量
b
的声明
空格是无关紧要的,因此为了使假定的声明
有建议的模糊性
/*A*/ struct a::b;
当然也会有同样的歧义。像那样重写,我们可能
我们同意,宣言的含义是显而易见的;但我们会
我想知道这个明显的意义是否被标准所证实
我将只考虑C++11标准。(我认为这是一项决议
C++03标准中的一个问题实际上更简单)
该标准将一元范围运算符:
与范围运算符区分开来
解析运算符:
§3.4.3限定名称查找,第1段:
类或命名空间成员或枚举数的名称可以在::scope解析后引用
运算符(5.1)应用于表示其类、命名空间或枚举的嵌套名称说明符
§3.4.3限定名称查找,第4段:
以一元范围运算符为前缀的名称::(5.1)在全局范围内的翻译单元中查找
在哪里使用它
这些引文并不是为了解释这种区别,只是为了表明这一点
它存在。但它们立即提供了一个要点,即在/*A*/
运营商必须是§3.4.3/4中的一元范围运营商
维持全局-::b
对/*A*/
的解释
显然,/*A*/
中的作用域运算符不是
一元的。但我们参考§5.1主要表达,了解更多信息
一元范围运算符和范围的语法定义
解析运算符,无论如何,我们还没有看到关于
当if是作用域的右操作数时,查找b
解析运算符
在§5.1.1/8中,我们发现操作员:
被定义为
§3.4.3/1中的中缀运算符,也作为
§3.4.3/4在合格id语法中:
当中缀运算符是一个字符的最终标记时,它就是中缀运算符
嵌套名称说明符,后跟模板
,以及
然后是一个非限定id,否则它是
背景:
:: identifier
:: operator-function-id
:: literal-operator-id
:: template-id
根据此语法,:
运算符必须与
嵌套名称说明符(构成范围解析运算符),如果
它可以。根据语法,/*a*/
中的a::
是嵌套的名称说明符
而a::b
是第一种形式的限定id
嵌套名称说明符模板[opt]unqualified-id
因此,我们确信§3.4.3限定名称查找适用于中的b
/*A*/
,可参考§3.4.3.1类成员,第1段,
对于该上下文中的b
应在a
中查找,而不是在全局中查找的结论:
如果限定id的嵌套名称说明符指定类,则在嵌套名称之后指定的名称-
在类(10.2)的范围内查找说明符,下面列出的情况除外
“下列情况”均不适用于/*A*/
,如果有任何疑问
嵌套类a::b
算作a
,§9.2类成员的一个成员,
第1款将其删除:
类的成员包括数据成员、成员函数(9.3)、嵌套类型和
统计员
发现a::b
错误地要求在a
中查找b
,
/*A*/
格式良好的问题变成了是否
/*A*/
是每个标准的声明(当然是struct A;
)
地点是)
是的,我们可以通过以下几个步骤来确保这一点:
声明语法:-
- 根据§7声明第1段,声明可以是简单声明, 一个简单的声明可以是decl说明符seq
- 根据§7.1说明符第1段,decl说明符seq可以是decl说明符, decl说明符可以是类型说明符
- 根据§7.1.6类型说明符第1段,类型说明符可以是 详细的类型说明符
- 根据§7.1.6.3详细类型说明符,第0段,详细类型说明符
可能是:
类键属性说明符seq[opt]嵌套名称说明符[opt]标识符
class
、struct
或union
(根据§9类,第1段)
和可选属性
:: identifier
:: operator-function-id
:: literal-operator-id
:: template-id
class-key nested-name-specifier identifier
error: forward declaration of struct cannot have a nested name specifier
error: use of undeclared identifier 'a'
warning: declaration ‘struct a::b’ does not declare anything
undefined reference to `b'