5

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

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

void f();

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

namespace N { void ::f(); }         // what about redeclaration?

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

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

struct A;

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

namespace N { struct ::A; }         // what about redeclaration?

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

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

4

1 回答 1

1

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

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

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

我在功能案例中没有看到问题;[dcl.meaning]/1确实允许它:

declarator-id被限定时,声明应引用限定符所指的类或命名空间的先前声明的成员(或者,在命名空间的情况下,该命名空间的内联命名空间集合的元素(7.3 .1)) 或其专业化;[…] [注意:如果限定符是全局::范围解析运算符,则declarator-id指的是在全局命名空间范围内声明的名称。——尾注]

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

于 2016-06-18T14:59:58.043 回答