在不包含原始声明的命名空间中重新声明
Redeclaration in a namespace that does not enclose the original declaration
命名空间成员可以在包含声明命名空间的命名空间中定义:
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.
void f();
namespace N { void ::f() {} } // illegal for definition
namespace N { void ::f(); } // what about redeclaration?
Class 可以在包含声明命名空间的命名空间中定义:
If a class-head-name contains a nested-name-specifier, the class-specifier shall refer to a class that was
previously declared directly in the class or namespace to which the nested-name-specifier refers, or in an
element of the inline namespace set (7.3.1) of that namespace (i.e., not merely inherited or introduced by
a using-declaration), and the class-specifier shall appear in a namespace enclosing the previous declaration.
In such cases, the nested-name-specifier of the class-head-name of the definition shall not begin with a
decltype-specifier.
struct A;
namespace N { struct ::A {}; } // illegal for definition
namespace N { struct ::A; } // what about redeclaration?
我们对成员函数定义和静态数据成员定义也有相同的规则。
所以我的问题是在不包含原始声明的命名空间中重新声明(不是定义)是否合法?
关于 struct ::A;
,[dcl.type.elab]/1 使您的声明格式错误:
If an elaborated-type-specifier is the sole constituent of a
declaration, the declaration is ill-formed unless it is an explicit
specialization (14.7.3), an explicit instantiation (14.7.2) or it
has one of the following forms:
class-key attribute-specifier-seqopt
identifier ;
friend
class-key
::
opt identifier ;
friend
class-key ::
opt simple-template-id ;
friend
class-key nested-name-specifier identifier
;
friend
class-key nested-name-specifier
template
opt simple-template-id ;
我没有发现函数案例中的问题; [dcl.meaning]/1 允许:
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; […]
[ Note: If the qualifier is the global ::
scope resolution operator, the declarator-id refers to a name declared
in the global namespace scope. — end note ]
但是,GCC 和 Clang 都坚持重新声明作为定义必须发生在封闭的命名空间中。
命名空间成员可以在包含声明命名空间的命名空间中定义:
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.
void f();
namespace N { void ::f() {} } // illegal for definition
namespace N { void ::f(); } // what about redeclaration?
Class 可以在包含声明命名空间的命名空间中定义:
If a class-head-name contains a nested-name-specifier, the class-specifier shall refer to a class that was previously declared directly in the class or namespace to which the nested-name-specifier refers, or in an element of the inline namespace set (7.3.1) of that namespace (i.e., not merely inherited or introduced by a using-declaration), and the class-specifier shall appear in a namespace enclosing the previous declaration. In such cases, the nested-name-specifier of the class-head-name of the definition shall not begin with a decltype-specifier.
struct A;
namespace N { struct ::A {}; } // illegal for definition
namespace N { struct ::A; } // what about redeclaration?
我们对成员函数定义和静态数据成员定义也有相同的规则。
所以我的问题是在不包含原始声明的命名空间中重新声明(不是定义)是否合法?
关于 struct ::A;
,[dcl.type.elab]/1 使您的声明格式错误:
If an elaborated-type-specifier is the sole constituent of a declaration, the declaration is ill-formed unless it is an explicit specialization (14.7.3), an explicit instantiation (14.7.2) or it has one of the following forms:
class-key attribute-specifier-seqopt identifier
;
friend
class-key::
opt identifier;
friend
class-key::
opt simple-template-id;
friend
class-key nested-name-specifier identifier;
friend
class-key nested-name-specifiertemplate
opt simple-template-id;
我没有发现函数案例中的问题; [dcl.meaning]/1 允许:
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; […] [ Note: If the qualifier is the global
::
scope resolution operator, the declarator-id refers to a name declared in the global namespace scope. — end note ]
但是,GCC 和 Clang 都坚持重新声明作为定义必须发生在封闭的命名空间中。