关于C ++:声明名称,引入名称和声明实体之间的区别

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 ;

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

在使用声明出现的声明区域中声明名称的含义是什么?

这是否意味着与将该名称引入使用声明所在的声明区域相同?

声明名称和声明名称所表示的实体之间是否也有区别?

例:

1
2
3
4
5
6
7
8
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? */


从第一原则出发,实体是从[基本]

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.

声明声明事物。要声明意味着它是由[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.

这些异常与这里无关,因为我们在谈论的是using-声明,而不是using-directives。让我对您的示例进行一些更改,以避免使用全局名称空间:

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

因此,首先,N::i是在名称空间N中声明并引入到N范围内的实体。现在,让我们添加一个using声明:

1
2
3
4
5
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声明该实体的同义词-不是新实体。


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

我将尝试用我对它的理解的示例来回答这个问题(请参阅所描述的代码中的注释):

1
2
3
4
5
6
7
//"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

下面是一个示例,其中(编译器)错误使该名称清晰可见:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#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;
}