在未包含原始声明的命名空间中重新声明

ign*_*tec 5 c++ namespaces definition language-lawyer redeclaration

可以在包含声明命名空间的命名空间中定义命名空间成员:

通过定义名称的显式限定(3.4.3.2),也可以在该命名空间外定义命名空间的成员,前提是已定义的实体已在命名空间中声明,并且定义出现在命名空间中的声明点之后包含声明的命名空间.

void f();

namespace N { void ::f() {} }       // illegal for definition

namespace N { void ::f(); }         // what about redeclaration?
Run Code Online (Sandbox Code Playgroud)

可以在包含声明命名空间的命名空间中定义类:

如果class-head-name包含嵌套名称说明符,则类说明符应引用先前在嵌套名称说明符所引用的类或命名空间中直接声明的类,或者在该命名空间的内联命名空间集(7.3.1)(即,不仅仅是由using-declaration继承或引入),并且类说明符应出现在包含前一个声明的命名空间中.在这种情况下,定义的类头名的嵌套名称说明符不应以decltype-specifier开头.

struct A;

namespace N { struct ::A {}; }      // illegal for definition

namespace N { struct ::A; }         // what about redeclaration?
Run Code Online (Sandbox Code Playgroud)

我们对成员函数定义和静态数据成员定义也有相同的规则.

所以我的问题是重新声明(不是定义)在没有包含原始声明的命名空间中是否合法?

Col*_*mbo 2

关于struct ::A;[dcl.type.elab]/1使您的声明格式不正确:

\n\n
\n

如果详细类型说明符是声明的唯一组成部分,则该声明是格式错误的,除非它是显式特化 (14.7.3)、显式实例化 (14.7.2) 或具有以下形式之一

\n\n

  类键属性说明符序列opt \n 标识符 ;
  friend 类键\n :: opt 标识符 ;
  friend\n 类键 ::opt 简单模板 ID ;
  friend 类键嵌套名称说明符标识符\n ;
  friend 类键嵌套名称说明符\ n template选择 简单模板 ID ;

\n
\n\n

我没有发现功能案例有问题;[dcl.meaning]/1确实允许:

\n\n
\n

当声明 符 id被限定时,声明应引用该限定符引用的类或命名空间的先前声明的成员(或者,在命名空间的情况下,引用内联命名空间集中的元素)该命名空间 (7.3.1)) 或其专业化;[\xe2\x80\xa6]\n [注意:如果限定符是全局::作用域解析运算符,则声明符 id引用在全局命名空间作用域中声明的名称。\xe2\x80\x94尾注]

\n
\n\n

然而,GCC 和 Clang 都坚持认为,作为定义的重新声明必须发生在封闭的命名空间中。

\n