What rule makes the following code compile without error:
using integer = int;
struct Foo
{
int integer;
};
int main() {
Foo f;
int integer;
f.integer;
}
using
is of course not a simple replacement for #define integer int
, but what makes this code apparently well-formed while int int;
would make it ill-formed?
While it's a little surprising that one can access a name declared in an outer scope, and then later hide that name , it's just a straightforward application of the rules for scoping:
A name declared in a block (9.3) is local to that block; it has block scope. Its potential scope begins at its point of declaration (6.3.2) and ends at the end of its block. [basic.scope.block]
In turn, the point of a name's declaration is:
immediately after its complete declarator (Clause 11) and before its initializer (if any)... [basic.scope.pdecl]
So when you do integer integer
, you haven't yet declared the block-scoped name integer
, which means you can still see the global integer
. This also means you cannot do integer integer = (integer)0
.
It's easier to explain why int int
won't compile. int
is a keyword, so no syntactic rule which could declare it as a name would be able to; it doesn't match the rules for "what a name looks like".
There are five kinds of tokens: identifiers, keywords, literals, operators, and other separators. [lex.token]
Because int
is a keyword, it cannot be an identifier, which means it cannot be a name.