名称空间中的重新声明不包含原始声明

时间:2016-06-18 14:01:34

标签: c++ namespaces language-lawyer definition redeclaration

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

  

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

void f();

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

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

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

  

如果类头名包含嵌套名称说明符,则类说明符应引用一个类   以前在嵌套名称说明符引用的类或命名空间中直接声明,或者在   该命名空间的内联命名空间集(7.3.1)的元素(即,不仅仅是由...继承或引入   使用声明),和类说明符应出现在包含前一个声明的命名空间中。   在这种情况下,定义的类头名的嵌套名称说明符不应以a开头   decltype说明符。

struct A;

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

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

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

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

1 个答案:

答案 0 :(得分:1)

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

  

如果 elaborated-type-specifier 是a的唯一成分   声明,声明格式不正确,除非是明确的   专门化(14.7.3),显式实例化(14.7.2)或它   具有以下形式之一

     

class-key attribute-specifier-seq opt   标识符 ;
friend class-key   :: opt 标识符 ;
friend    class-key :: opt simple-template-id ;
friend < em> class-key nested-name-specifier identifier   ;
friend class-key nested-name-specifier   template opt simple-template-id ;

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

  

当    declarator-id 是合格的,声明应引用先前声明的类或命名空间的成员   限定符所引用的(或者,在命名空间的情况下,该命名空间的内联命名空间集合的元素(7.3.1))或其特化; [...]   [注意:如果限定符是全局::范围解析运算符,则 declarator-id 引用声明的名称   在全局命名空间范围内。 - 结束记录]

但是,GCC和Clang都坚持认为重新声明作为定义必须在封闭的命名空间中进行。