Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can a local variable have the same name as a namespace?

GCC, clang and VS2013 compile the snippet below:

namespace A{}
int main()
{
    int A;
}

However [namespace.alias]/4 says the following:

A namespace-name or namespace-alias shall not be declared as the name of any other entity in the same declarative region.

and

[basic.scope.declarative]/1 says:

Every name is introduced in some portion of program text called a declarative region, which is the largest part of the program in which that name is valid, that is, in which that name may be used as an unqualified name to refer to the same entity.

That is, I have the impression that the int variable in main() cannot have the same name as the namespace A. Observe that the example in [basic.scope.declarative]/2 seems to corroborate this when it says

The declarative region of the first j includes the entire example.

like image 424
Leon Avatar asked Apr 21 '15 14:04

Leon


2 Answers

From [basic.scope.declarative], the definition of a "declarative region" is:

Every name is introduced in some portion of program text called a declarative region, which is the largest part of the program in which that name is valid, that is, in which that name may be used as an unqualified name to refer to the same entity.

The restriction is, emphasis mine:

Given a set of declarations in a single declarative region, each of which specifies the same unqualified name
— they shall all refer to the same entity, or all refer to functions and function templates

Going back to your example. If we annotate the two declarative regions, we have:

namespace A{}    + region #1
                 |
int main()       |           +
{                |           |
    int A;       |           | region #2               
                 |           |
}                +           +

The declarative regions for namespace A (#1) and int A (#2) are different (the second is a strict subset of the first, but that doesn't matter). Since they are different, the restriction on having a single name doesn't apply. There is one single A in #2 and one single A in #1.

If we, however, moved int A to be in the same declarative region:

namespace A {}     +   the only declarative region. even though the
int A;             |   potential scope of "int A" does not include
                   |   "namespace A", the declarative region does.
int main() {       |   The intent of this is expressed in the example
                   |   in [basic.scope.declarative]/2:
                   |        int main() {
                   |            int i = j, j;
                   |            j = 42;
                   |        }
                   |
                   |   "The declarative region of the [j] includes all 
                   |    the text between { and }, but its potential scope
}                  +    excludes the declaration of i."

That would violate [basic.scope.declarative]/4, and both gcc and clang correctly reject the code with:

error: redefinition of 'A' as different kind of symbol

Note that as Vaughn Cato points out, there is an active defect report about the wording for declarative region.

like image 68
Barry Avatar answered Oct 06 '22 00:10

Barry


The first quote you mention [namespace.alias]/4 was actually there to cover extension namespaces and is the subject of a defect report and was subsequently removed and replaced with more specific wording. We can see from DR 1795 which says:

According to 7.3.1 [namespace.def] paragraph 2,

The identifier in an original-namespace-definition shall not have been previously defined in the declarative region in which the original-namespace-definition appears.

Apparently the intent of this requirement is to say that, given the declarations

namespace N { }
namespace N { }

the second declaration is to be taken as an extension-namespace-definition and not an original-namespace-definition, since the general rules in 3.3.1 [basic.scope.declarative] cover the case in which the identifier has been previously declared as something other than a namespace.

and tells us that 3.3.1 [basic.scope.declarative] covers the case you are referring to, which it does in paragraph 1:

Every name is introduced in some portion of program text called a declarative region, which is the largest part of the program in which that name is valid, that is, in which that name may be used as an unqualified name to refer to the same entity. In general, each particular name is valid only within some possibly discontiguous portion of program text called its scope. To determine the scope of a declaration, it is sometimes convenient to refer to the potential scope of a declaration. The scope of a declaration is the same as its potential scope unless the potential scope contains another declaration of the same name. In that case, the potential scope of the declaration in the inner (contained) declarative region is excluded from the scope of the declaration in the outer (containing) declarative region.

and 3:

Given a set of declarations in a single declarative region, each of which specifies the same unqualified name,

  • they shall all refer to the same entity, or all refer to functions and function templates;
like image 41
Shafik Yaghmour Avatar answered Oct 06 '22 00:10

Shafik Yaghmour