问题描述
什么规则使得以下代码为compile without error:
using integer = int;
struct Foo
{
int integer;
};
int main() {
Foo f;
int integer;
f.integer;
}
using
当然不是#define integer int
的简单替代,但是什么使这段代码显然格式正确,而int int;
却使其格式错误?
解决方法
虽然可以访问在外部作用域中声明的名称,然后再隐藏该名称,这有点令人惊讶,但这只是范围规则的直接应用:
在块(9.3)中声明的名称是该块的本地名称;它具有块范围。它的潜在范围始于其 声明点(6.3.2),并在其块末尾结束。 [basic.scope.block]
反过来,名称声明的重点是:
紧随其完整的声明符(第11条)之后, 初始化程序(如果有)... [basic.scope.pdecl]
因此,当您执行integer integer
时,尚未声明块作用域名称integer
,这意味着您仍然可以看到全局integer
。这也意味着您不能执行integer integer = (integer)0
。
更容易解释为什么int int
无法编译。 int
是一个关键字,因此没有句法规则可以将其声明为名称。它不符合“名字看起来”的规则。
有五种令牌:标识符,关键字,文字,运算符和其他分隔符。 [lex.token]
因为int
是关键字,所以它不能是标识符,这意味着它不能是名称。
代码编译的原因是integer
的使用在不同的范围中。
using integer = int; // #1
struct Foo
{
int integer; // #2
};
请注意,integer
中的#1
和#2
之间没有任何关系。这些用法之间没有冲突,而且它们的名称也可能不同。
在Foo
内,符号integer
仅指代变量。如果要引用类型别名,可以在::
之前加上前缀,如下所示:
struct Foo
{
::integer integer; // ok
};
如果using
声明和变量在 same 范围内,则会出现错误:
using integer = int;
int integer; // error,redefinition of symbol
// as different kind of entity
或
struct Foo
{
using integer = int;
int integer; // error,redefinition of symbol
// as different kind of entity
};