问题
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 typename
optnested-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 i
s 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