Repeated extern declarations of qualified C ++ identifiers

Why can't qualified names be redeclared inside functions?

The following code cannot be compiled (in MSVC2015 and clang)

int i; namespace N { int j; } void foo() { extern int i; extern int i; extern int N::j; extern int N::j; } int main() { return 0; } 

However, if we move the two lines extern int N::j; immediately before void foo() , then the code compiles fine.


UPDATE It should be noted that

  • unqualified name declarations are repeated
  • both ::i and ::N::j have already been defined in their respective declarations,
  • ::N::j not showing foo
  • grammar allows extern int ::N::j and this is not a definition
  • The following code also doesn't work (thanks TC for pointing this out)

.

 int i; void foo() { extern int ::i; } 
  1. the following code works in MSVC, but it gives a warning in clang

.

 int i; extern int ::i; 
+4
source share
2 answers

TC directed me to [dcl.meaning] p1

... When the declaration identifier is qualified, the declaration refers to a previously declared member of the class or namespace to which the qualifier belongs (or, in the case of a namespace, an element of the built-in namespace this namespace (7.3.1)) or its specialization. ..

It seems to me that this is the case when the standard is incorrectly represented by the implementation.

+2
source

This is a namespace member definition and declaration problem. See C ++ 11 spec:

7.3.1.2 Namespace element definitions [namespace.memdef]

1 Members (including explicit template specializations (14.7.3)) a namespace can be defined inside this namespace. [Example: namespace X {void f () {/.../}} -end example]

2 The members of a named namespace can also be defined outside this namespace using an explicit (3.4.3.2) definition of the name, provided that the entity defined has already been declared in the namespace and the definition appears after the declaration point in the namespace which encloses the ad namespace.

Therefore, the code below is compiled.

 int i; namespace N { int j; void foo() { extern int i; extern int j; } } void foo() { extern int i; using namespace N; extern int j; } int main() { return 0; } 

Here is a general example of using extern with namespace : In a single CPP file:

 namespace N { int j; } 

In your header file:

 namespace N { extern int j; } 

Update:

More on extern, namespace, declaration and definition

The scope statement cannot be used for declarations. It can be used to determine. Using declaration: for extern will be poorly formed. See C ++ 11 spec:

7.5 Communication characteristics [dcl.link] ......
4 Binding specification. When the socket specification is binding, the innermost one defines language relationships. The binding specification does not establish the scope. The communication specification should only be performed in the namespace (3.3). In the binding specification, the specified language relationship applies to function types of the entire function declarators, function names with external connection, and variable names with external connection declared in the binding specification.

3.3.6 Namespace scope [basic.scope.namespace]

1 The declarative scope of a namespace is its namespace ....

 // Compiled with VC2013. // extern int ::i; // error C2039: 'i' : is not a member of '`global namespace'' extern int i; // declaration int i; // definition namespace N { extern int j; // declaration } int N::j; // definition namespace N { // int j; // definition } void foo() { // extern int ::i; // fatal error C1506: unrecoverable block scoping error extern int i; // declaration // extern int N::j; // error C2086: 'int N::j' : redefinition } int main() { return 0; } 
+1
source

All Articles