Search code examples
c++language-lawyerusingtype-alias

Why type alias is allowed as name of variable?


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?


Solution

  • 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.