命名空间标识符的范围是什么?

时间:2015-12-13 04:26:02

标签: c++ language-lawyer

命名空间标识符的声明声明性区域范围似乎没有明确的定义/ strong>,除了命名空间内的标识符 - 根据标准(§3.3.6/ 1)。

  

命名空间定义的声明性区域是其namespace-body。潜在的范围表示为   原始名称空间名称是由每个名称建立的声明区域的串联   命名空间定义在同一个......

虽然标准确实涉及声明 -a 命名空间定义的声明,但这不适用于命名空间定义的情况,因为它没有根据标准(§3.3.2/ 1),声明符初始化程序

  

名称的声明点紧跟在其完整声明者(第8条)之后和之前   初始化程序(如果有的话),除非如下所述......

然后,我如何确定命名空间标识符的那些?

2 个答案:

答案 0 :(得分:4)

根据您从标准中引用的文字,我的解释是您回答了自己的问题。

正如您所说,命名空间不能具有完整的声明符,因为可以在任何编译单元(即源文件或该源文件包含的头文件)中为任何名称空间X创建一个额外的声明区域。 namespace X { <new names within this declarative region> }

由于永远不会有命名空间的完整声明,因此命名空间永远不会有声明点。由于没有声明点,因此没有命名空间标识符这样的东西,也没有一个范围。

这意味着命名空间只是一个标签,可以作为标识符的一部分。 istream是名称空间std中的标识符,该标识符的完整名称(从名称空间std的声明区域外的代码引用)是std::istream。所有using namespace std;所做的是,当试图找到潜在标识符foo的匹配时,告诉编译器在命名空间std(或它具有可见性的声明性区域)中查找名为foo的标识符,它将成为候选匹配项。 [这就是为什么多个名称空间的using namespace可能导致歧义,如果多个名称空间包含相同的标识符]。

答案 1 :(得分:1)

我会尝试根据对操作的误解将其分解为部分。

他说:

  

似乎没有明确的定义   声明,声明性区域,命名空间标识符的范围

// File A.h
namespace foo {        // Resides At Global Scope
    // some code here.
    void bar();        // Resided At foo:: Scope
}

// File A.cpp
namespace foo {
    // some more code here
    void bar() { 
        std::cout << "Hell World" << std::endl; 
    }
}

这里声明性区域跨越foo的多个文件,其定义和声明为foofoo是其标识符。由于这是一个命名的命名空间,因此没有声明器,如第8.1节中定义的变量,函数或类型所示。

  

声明符声明一个变量,函数或类型   声明

并且没有初始化器,因为它是命名空间。它是一个具有范围的声明性区域。

而我认为操作系要求的是:

  

然后,我如何确定命名空间标识符的那些?

名称空间标识符是名称空间的名称,也是其定义和声明。从某种意义上说,所有3都是同一个,命名空间的声明区域和它的范围是同一个。

不,标准没有清楚地描述命名空间的声明点,因为它指的是使用命名空间没有的declator。在某些情况下,命名空间可以在其定义时由另一个命名空间初始化 - 声明如下:通常是别名!

namespace someLongName{
}

namespace shortVersion = someLongName {
}

如果在3.3.2.1中找到声明点,如果你继续通过本节中的分离,则转到块范围,函数原型范围,函数范围,命名空间范围,类范围,枚举范围,模板参数范围,但是,如果你在声明和定义的定义中回顾3.1;名称空间已定义且未声明,但在3.3.6节中

  

命名空间定义的声明性区域就是它   命名空间体。在名称空间体中声明的实体据说是   命名空间的成员以及这些声明引入的名称   进入命名空间的声明区域被称为成员   命名空间的名称。名称空间成员名称具有名称空间范围   它的潜在范围包括名称命名空间   声明(3.3.2)以后;并且对于每个使用指令(7.3.4)   提名成员的名称空间,成员的潜在范围   包括使用指令的潜在范围的那部分   在成员的声明之后。

7.3 1&amp; 2

  

7.3命名空间[basic.namespace] 1命名空间是一个可选命名的声明性区域。命名空间的名称可用于访问   在该命名空间中声明的实体也就是说,成员   命名空间。与其他声明性区域不同,a的定义   命名空间可以拆分为一个或多个转换的几个部分   单位。 2翻译单元的最外层声明区域是a   命名空间;见3.3.6。

7.3.1 2-4

  

2每个命名空间定义都应出现在全局范围或a中   命名空间范围(3.3.6)。   3在命名空间定义中,标识符是标识符的名称   命名空间。如果标识符在查找时(3.4.1),则引用a   在...中引入的namespace-name(但不是命名空间别名)   声明区域,其中出现named-namespace-definition,   namespace-definition扩展了先前声明的命名空间。   否则,标识符将作为名称空间名称引入到   声明区域,其中出现了named-namespace-definition。   4因为名称空间定义包含其中的声明   namespace-body和namespace-definition本身就是一个声明,它   遵循命名空间定义可以嵌套。

在这里,我将尝试建议即使没有明确的定义,命名空间的声明点紧跟在其标识符 - 定义 - 声明之后!

namespace /*keyword*/ std /*definition, declaration, identifier*/ (point of declaration) { /*beginning of declarative region & scope*/  
    .... // some code

} // End of declarative region or scope until another matching identifier at same level of scope is found. 
  // And this can span multiple translations units.

我希望这可以解决这个困惑。