[英]repeated extern declarations of qualified identifiers C++
Why is it that qualified names cannot be re-declared inside functions? 为什么合格的名称不能在函数内重新声明?
The following code fails to compile (in MSVC2015 and clang) 以下代码无法编译(在MSVC2015和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;
但是,如果我们移动两行extern int N::j;
to just before void foo()
then the code compiles fine. 就在void foo()
之前,代码编译得很好。
UPDATE It is noteworthy that 更新值得注意的是
::i
and ::N::j
were already defined in their respective declarations, ::i
和::N::j
都已在各自的声明中定义, ::N::j
is not visible to foo
::N::j
对foo
不可见 extern int ::N::j
and it is not a definition 语法允许extern int ::N::j
并且它不是定义 . 。
int i;
void foo()
{
extern int ::i;
}
. 。
int i;
extern int ::i;
TC directed me to [dcl.meaning]p1 TC指导我[dcl.meaning] p1
… When the declarator-id is qualified, the declaration shall refer to a previously declared member of the class or namespace to which the qualifier refers (or, in the case of a namespace, of an element of the inline namespace set of that namespace (7.3.1)) or to a specialization thereof … ...当declarator-id被限定时,声明应引用先前声明的限定符所引用的类或命名空间的成员(或者,如果是命名空间,则引用该命名空间的内联命名空间集的元素) 7.3.1))或其专业化......
It seems to me that this is a case where the standard is not faithfully represented by the implementations. 在我看来,这是一个案例,其中标准没有忠实地表示实现。
It is the namespace member definition vs. declaration issue here. 这是命名空间成员定义与声明问题。 Please see C++11 spec: 请参阅C ++ 11规范:
7.3.1.2 Namespace member definitions [namespace.memdef] 7.3.1.2命名空间成员定义[namespace.memdef]
1 Members (including explicit specializations of templates (14.7.3)) of a namespace can be defined within that namespace. 1可以在该命名空间中定义命名空间的成员(包括模板的显式特化(14.7.3))。 [ Example: namespace X { void f() { / ... / } } —end example ] [示例:名称空间X {void f(){/ ... /}} - 示例]
2 Members of a named namespace can also be defined outside that namespace by explicit qualification (3.4.3.2) of the name being defined, provided that the entity being defined was already declared in the namespace and the definition appears after the point of declaration in a namespace that encloses the declaration's namespace. 2通过定义名称的显式限定(3.4.3.2),也可以在该命名空间外定义命名命名空间的成员,前提是已定义的实体已在命名空间中声明,并且定义出现在声明中的声明之后包含声明命名空间的命名空间。
Therefore, the revised code below compiles. 因此,下面的修订代码编译。
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 generic example of using extern
with namespace
: In one CPP file: 以下是使用extern
with namespace
的一般示例:在一个CPP文件中:
namespace N
{
int j;
}
In its header file: 在其头文件中:
namespace N
{
extern int j;
}
Update: 更新:
The :: scope resolution operator cannot be use for declaration. :: scope resolution运算符不能用于声明。 It may be used for definition. 它可以用于定义。 Using :: for extern
declaration would be ill-formed. 使用:: for extern
声明将是不正确的。 Please see C++11 spec: 请参阅C ++ 11规范:
7.5 Linkage specifications [dcl.link] ... ... 7.5链接规范[dcl.link] ......
4 Linkage specifications nest. 4连杆规格嵌套。 When linkage specifications nest, the innermost one determines the language linkage. 当链接规范嵌套时,最里面的规则确定语言链接。 A linkage specification does not establish a scope. 链接规范不会建立范围。 A linkage-specification shall occur only in namespace scope (3.3). 链接规范只应在命名空间范围内发生(3.3)。 In a linkage-specification, the specified language linkage applies to the function types of all function declarators, function names with external linkage, and variable names with external linkage declared within the linkage-specification. 在链接规范中,指定的语言链接适用于所有函数声明符的函数类型,具有外部链接的函数名称,以及在链接规范中声明的具有外部链接的变量名称。3.3.6 Namespace scope [basic.scope.namespace] 3.3.6命名空间范围[basic.scope.namespace]
1 The declarative region of a namespace-definition is its namespace-body. 1命名空间定义的声明性区域是其namespace-body。 … ...
// 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;
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.