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

吃可爱长大的小学妹 提交于 2021-02-18 22:30:28

问题


From the C++11 standard, §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 typenameoptnested-name-specifier unqualified-id ;
using :: unqualified-id ;

The member name specified in a using-declaration is declared in the declarative region in which the using-declaration appears.

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

Does this mean the same as introducing that name into the declarative region where the using-declaration occurs?

Also is there a difference between declaring a name and declaring the entity that the name denotes?

Example:

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? */ 

回答1:


From first principles, an entity is, from [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.

Declarations declare things. To be declared means that it was introduced by a declaration, from [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 of those exceptions are relevant here, since we're talking about using-declarations and not using-directives. Let me alter your example somewhat so as to avoid the global namespace:

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

So to start with, N::i is an entity that is declared in namespace N and introduced into the scope of N. Now, let's add a using-declaration:

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

From [namespace.udecl], we have:

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.

The using-declaration using N::i does not name a constructor, so rather than having the name i be a new entity, it is instead a synonym for N::i.

So basically, both is are names introduced in and declared in their respective namespaces. In N, i declares an entity with static linkage, but in B, i declares a synonym to that entity - not a new entity.




回答2:


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

I'll try and answer this with an example of my understanding of it (Refer to my comments in the depicted code):

// "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

Below is an example where the (compiler) error makes it clear where the name is not visible:

#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;
}


来源:https://stackoverflow.com/questions/31708705/the-difference-between-declaring-a-name-introducing-a-name-and-declaring-an-en

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!