声明名称、引入名称和声明实体的区别

The difference between declaring a name, introducing a name, and declaring an entity

来自 C++11 标准,§7.3.3[namespace.udecl]/1:

A using-declaration introduces a name into the declarative region in which the using-declaration appears.

using-declaration:

using typenameopt nested-name-specifier unqualified-id ;
using :: unqualified-id ;

using 声明中指定的成员名称在出现 using 声明的声明区域中声明。

在出现 using 声明的声明区域中声明的名称是什么意思?

这是否与将该名称引入出现 using 声明的声明区域相同?

另外声明名称和声明名称所代表的实体有区别吗?

示例:

namespace N { static int i = 1; } /* Declares an entity denoted by 
    the name i in the declarative region of the namespace N. 
    Introduces the name into the declarative region of the namespace N.
    Declares the name i in the declarative region of the namespace N? */
using N::i; /* Declares the name i in the declarative region of the
    global namespace. Also introduces that name into the declarative
    region of the global namespace? Also declares the entity that the
    name i denotes? */ 

What do they mean by the name being declared in the declarative region where the using-declaration occurs?

我会试着用我理解的例子来回答这个问题(参考我在描述的代码中的评论):

// "namespace X {}" introduces a declarative region of the namespace X
namespace X {
  //The name SomeObject is now introduced into the declarative region X
  // It is only visible in that declarative region
  using Y::SomeObject;
}//Declarative region X ENDS here
// SomeObject NOT visible here

下面是一个示例,其中(编译器)错误清楚地表明了名称不可见的地方:

#include <iostream>

namespace A
{
  struct X{};
}

namespace B
{
  struct X{};
}

namespace C
{
  using A::X;

  void foo(X){}
}

namespace D
{
  using B::X;

  void foo(X){}
}

void foo(X){} //FAILS TO COMPILE - DELIBERATE!!!

int main() 
{
    return 0;
}

根据第一原理,实体是[basic]

a value, object, reference, function, enumerator, type, class member, bit-field, template, template specialization, namespace, parameter pack, or this. [...] Every name that denotes an entity is introduced by a declaration.

声明声明事物。 to be declared的意思是通过声明引入的,来自[basic.scope.declarative]

Every name is introduced in some portion of program text called a declarative region, which is the largest part of the program in which that name is valid, that is, in which that name may be used as an unqualified name to refer to the same entity.

The names declared by a declaration are introduced into the scope in which the declaration occurs, except that the presence of a friend specifier (11.3), certain uses of the elaborated-type-specifier (7.1.6.3), and using-directives (7.3.4) alter this general behavior.

None 这些异常与此处相关,因为我们谈论的是 using-declarations 而不是 using-directives.让我稍微改变一下你的例子,以避免全局命名空间:

namespace N {        //  + declarative region #1
                     //  |
    static int i;    //  | introduces a name into this region
                     //  | this declaration introduces an entity
}                    //  +

所以首先,N::i 是在命名空间 N 中声明并引入 N 范围的实体。现在,让我们添加一个 using-declaration:

namespace B {        //  + declarative region #2
                     //  |
    using N::i;      //  | declaration introduces a name i
                     //  | but this is not an entity
}                    //  +

从 [namespace.udecl],我们有:

If a using-declaration names a constructor (3.4.3.1), it implicitly declares a set of constructors in the class in which the using-declaration appears (12.9); otherwise the name specified in a using-declaration is a synonym for a set of declarations in another namespace or class.

using-declaration using N::i 没有命名构造函数,因此 i 不是一个新实体,而是一个N::i 的同义词

所以基本上,i都是在各自的命名空间中引入和声明的名称。在 N 中,i 声明了一个具有静态链接的实体,但在 B 中,i 声明了该实体的同义词 - 而不是新实体。