命名空间中定义类的样式的有效性

Validity of style of defining class in namespace

本文关键字:样式 有效性 定义 命名空间      更新时间:2023-10-16

摘要:

是否有任何文档(例如c++标准)支持使用以下样式定义c++类的有效性:

namespace N { class X; }
class N::X { ... }

详细信息:

我们在公司的一些代码中使用了几种风格来定义类:

// n_x.h - style 1
namespace N {
  class X;
}
class N::X {...}

// n_y.h - style 2
namespace N {
  class Y;
}
namespace N {
  class Y { ... };
}

这里的关键区别在于样式1中的class N::X风格2namespace N { class Y {...}... 之间,即我们将款式2中的类Y封装在命名空间中。

对我来说,这两种风格似乎都是有效的(我们在VS20xx和Clang上从未遇到过编译它们的问题),但一位同事质疑风格1是否有效,因为我们用来分析代码的工具在使用样式1时无法正确识别类X是命名空间的一部分。

我希望有人能为我提供一份文档参考,该文档表明样式1是在C++中定义类的有效方法。

是的,样式1是有效的。

[namespace.memdef]/2状态:

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

也许Bjarne Stroustrup书中的这句话可以为你服务。

摘自《C++程序设计语言》第四版第14章:

-----(第392页)

[…]

14.2.1明确资格

成员可以声明为winthina命名空间定义,稍后使用命名空间名称::成员名称表示法。

命名空间的成员必须是使用这种表示法引入:

namespace namespace-name {
   // declarations and definitions
}

例如:

namespace Parser {
     double expr(bool); //declaration
     double term(bool);
     double prim(bool);
}
double val = Parser::expr(true); // use
double Parser::expr(bool b) //definition
{
    // ...
}

我们不能使用限定符语法(iso.7.3.1.2)在命名空间定义之外声明命名空间的新成员…

§9[class]/p11:

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

类头名称是为正在定义的类命名的事物的术语嵌套名称说明符是"::左侧的所有内容,包括::本身"的标准语。

来自A.8 Classes [gram.class]:

...
class-specifier:
    class-head { member-specification_opt }
class-head:
    class-key attribute-specifier-seq_opt class-head-name class-virt-specifier_opt
    base-clause_opt class-key attribute-specifier-seq_opt base-clause_opt
class-head-name:
    nested-name-specifier_opt class-name
class-virt-specifier:
    final
class-key:
    class
    struct
    union

因此,在class-key关键字和class-name之间允许一个可选的nested-name-specifiernested-name-specified记录在A.4 Expressions [gram.expr]:中

nested-name-specifier:
    ::
    type-name ::
    namespace-name ::
    decltype-specifier ::
    nested-name-specifier identifier ::
    nested-name-specifier template_opt simple-template-id ::

因此namespace-names在定义中是有效的。