为什么不能在函数内重新声明限定名?
以下代码无法编译(在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;
}
但是,如果我们将两行extern int N::j;
移到void foo()
之前,那么代码编译就可以了。
更新值得注意的是
::i
和::N::j
已在各自的声明中定义,::N::j
对foo
不可见
extern int ::N::j
而不是定义
int i;
void foo()
{
extern int ::i;
}
int i;
extern int ::i;
答案 0 :(得分:2)
T.C。指示我[dcl.meaning] p1
...当declarator-id被限定时,声明应引用先前声明的限定符所引用的类或命名空间的成员(或者,如果是命名空间,则引用内联命名空间集的元素)该命名空间(7.3.1))或其专业化......
在我看来,这是一个标准没有被实施忠实代表的情况。
答案 1 :(得分:1)
这里是命名空间成员定义与声明问题。请参阅C ++ 11规范:
7.3.1.2命名空间成员定义[namespace.memdef]
1个成员(包括模板的明确专业化(14.7.3)) 命名空间可以在该命名空间中定义。 [示例:名称空间X. {void f(){/ ... /}} -end example]
2名成员 命名空间也可以通过显式在该命名空间外定义 定义名称的资格(3.4.3.2),前提是 正在定义的实体已经在命名空间中声明了 定义出现在命名空间中的声明点之后 包含声明的命名空间。
因此,下面修改后的代码编译。
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;
}
以下是extern
与namespace
一起使用的一般示例:
在一个CPP文件中:
namespace N
{
int j;
}
在其标题文件中:
namespace N
{
extern int j;
}
更新:
:: scope resolution运算符不能用于声明。它可以用于定义。使用:: for extern
声明将是不正确的。
请参阅C ++ 11规范:
7.5链接规范[dcl.link] ...... ... 4连杆规格嵌套。当连接规格嵌套时,最里面 一个决定了语言的联系。 链接规范没有 建立范围。链接规范只能在 命名空间范围(3.3)。在链接规范中,指定的 语言链接适用于所有函数的函数类型 声明符,具有外部链接的函数名称和变量名称 在链接规范中声明了外部链接。
3.3.6命名空间范围[basic.scope.namespace]
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;
}