命名空间中定义类的风格有效性

3

摘要:

有没有任何文件(例如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样��2 中的namespace N { class Y {...}... ,即我们在样式2中将类Y包装在命名空间中。
对我来说,这两种风格都是有效的(我们从未在VS20xx和Clang上编译它们时遇到过问题),但我的一个同事质疑 样式1 是否有效,因为我们正在使用的工具没有正确识别 class X 是命名空间的一部分。
我希望有人能向我提供参考文献,证明 样式1 是定义C ++类的有效方式。

1
我投票支持style 2,因为如果命名空间中有多个类和结构体,更改命名空间的名称会(稍微)容易一些。 - borisbn
风格1有优点。它可以避免一层缩进并且更早地发现拼写错误。 - Simple
我开始使用样式1是因为缩进问题(正如Simple所提到的)- 工具开始干扰我的缩进,或者当你有嵌套的命名空间时,它会变得有点混乱。但是,两种风格都有优缺点。 - Andrew Wyatt
4个回答

4

是的,样式1是有效的。

[namespace.memdef]/2规定:

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


+1 不错的发现... 3.4.2/7 甚至说明了早期命名空间如何基于“using”语句进行匹配,而后期命名空间在成员函数定义期间明确列出... - Tony Delroy

1

也许Bjarne Stroustrup的书中的这句话可以帮到您。

来自The C++ Programming Language, Fourth Edition第14章:

----- (第392页)

[...]

14.2.1 显式限定

成员可以在命名空间定义内声明,并使用namespace-name::member-name符号稍后定义。

必须使用此符号引入命名空间的成员:

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)在命名空间定义外声明命名空间的新成员。

我只有《C++程序设计语言 第三版》(http://www.stroustrup.com/3rd.html),但在第8.2节,第167-169页中有类似的段落 - 感谢这个可靠的来源。 - Andrew Wyatt

0

来自 A.8 类 [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-specifier”。在“A.4 Expressions [gram.expr]”中有关于“nested-name-specified”的文档记录。
nested-name-specifier:
    ::
    type-name ::
    namespace-name ::
    decltype-specifier ::
    nested-name-specifier identifier ::
    nested-name-specifier template_opt simple-template-id ::

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


0

§9 [类名]/p11:

如果一个class-head-name包含一个nested-name-specifier,则该class-specifier应指向之前直接在类或命名空间中声明的类,或该命名空间的inline namespace set (7.3.1) 的元素(即不仅是通过using-declaration继承或引入的类),并且该class-specifier必须出现在封闭先前声明的命名空间中。在这种情况下,定义的class-head-namenested-name-specifier不应以decltype-specifier开头。

class-head-name是指定义的类的名称。nested-name-specifier是指“::”左侧的所有内容,包括“::”本身。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接