* C++ namespace using directives
@ 2002-04-16 14:41 Jim Blandy
2002-04-16 19:39 ` Gabriel Dos Reis
2002-04-22 14:52 ` Don Howard
0 siblings, 2 replies; 5+ messages in thread
From: Jim Blandy @ 2002-04-16 14:41 UTC (permalink / raw)
To: gdb
Could a C++ person check my understanding of `using namespace'
directives?
I'm reading Stroustrup, and the more I read about `using namespace',
the weirder it gets. Check this out:
namespace A
{
int x;
int y;
int z;
};
void f ()
{
int *x;
{
int *y;
using namespace A;
*x; /* `x' refers to local x, not A::x */
*y; /* `y` refers to local y, not A::y */
z; /* `z' refers to A::z */
}
}
This program is type-correct, so you can see exactly which definitions
those identifiers refer to. I ran it through the newest GCC, and it
didn't complain about ambiguities. Stroustrup C.10.1 agrees.
Weird, huh? Although the `using namespace' directive does make A's
variables visible, A's bindings are still *shadowed* by local
variables in blocks that *enclose* the one containing the `using
namespace' directive.
So, here's the way I'd describe the effect of a `using namespace'
directive:
To look up some identifier X in a scope that has a `using namespace N'
directive, search for both X and N::X. If you find more than one
match, report an ambiguity. (But see below for a subtlety in the
definition of an "ambiguity".)
Now, suppose you've got nested compound statements. In the absence of
namespaces, you start at the innermost enclosing block, and work your
way out looking for a binding. In the presence of `using namespace'
directives, you accumulate extra prefixes to search under as you go
out.
So in this case:
namespace A
{
int x;
int *y;
};
void
f ()
{
using namespace A;
{
int *x;
*x; /* `x' refers to local x */
*y; /* `y' refers to A::y */
}
}
Since B has no binding for x, the reference in `*x' refers to the
local x, without ambiguity, even though A is `used' in an enclosing
scope.
Regarding what constitutes an "ambiguity": if the same declaration
makes it into a scope under two different names, that's not considered
an ambiguity. So the compiler accepts the following without
complaint.
namespace A
{
int x;
};
namespace B
{
using A::x;
};
void
f ()
{
using namespace A;
using namespace B;
x;
}
However, if we give namespace B its own `int x' definition, the
compiler does complain.
Is this all correct?
^ permalink raw reply [flat|nested] 5+ messages in thread* Re: C++ namespace using directives
2002-04-16 14:41 C++ namespace using directives Jim Blandy
@ 2002-04-16 19:39 ` Gabriel Dos Reis
2002-04-22 14:52 ` Don Howard
1 sibling, 0 replies; 5+ messages in thread
From: Gabriel Dos Reis @ 2002-04-16 19:39 UTC (permalink / raw)
To: Jim Blandy; +Cc: gdb
Jim Blandy <jimb@redhat.com> writes:
| Could a C++ person check my understanding of `using namespace'
| directives?
|
| I'm reading Stroustrup, and the more I read about `using namespace',
| the weirder it gets.
:-)
| Check this out:
|
| namespace A
| {
| int x;
| int y;
| int z;
| };
|
| void f ()
| {
| int *x;
|
| {
| int *y;
| using namespace A;
|
| *x; /* `x' refers to local x, not A::x */
| *y; /* `y` refers to local y, not A::y */
| z; /* `z' refers to A::z */
| }
| }
|
| This program is type-correct, so you can see exactly which definitions
| those identifiers refer to. I ran it through the newest GCC, and it
| didn't complain about ambiguities. Stroustrup C.10.1 agrees.
Yes. That matches the standard requirement:
3.4.1/2
The declarations from the namespace nominated by a using-directive
become visible in a namespace enclosing the using-directive; see
7.3.4. For the purpose of the unqualified name lookup rules
described in 3.4.1, the declarations from the namespace nominated by
the using-directive are considered members of that enclosing namespace.
So in the above program, after the 'using namespace A', A::x and A::y
are considered (for the name lookup process) as members of the global
namespace. So they are hidden by the local definitions in f().
| Weird, huh? Although the `using namespace' directive does make A's
| variables visible, A's bindings are still *shadowed* by local
| variables in blocks that *enclose* the one containing the `using
| namespace' directive.
Exact.
| So, here's the way I'd describe the effect of a `using namespace'
| directive:
|
| To look up some identifier X in a scope that has a `using namespace N'
| directive, search for both X and N::X.
In the transitive closure of the enclosing namespace.
[...]
| Regarding what constitutes an "ambiguity": if the same declaration
| makes it into a scope under two different names, that's not considered
| an ambiguity.
Right.
[...]
| However, if we give namespace B its own `int x' definition, the
| compiler does complain.
Right,
| Is this all correct?
Yes.
-- Gaby
^ permalink raw reply [flat|nested] 5+ messages in thread* Re: C++ namespace using directives
2002-04-16 14:41 C++ namespace using directives Jim Blandy
2002-04-16 19:39 ` Gabriel Dos Reis
@ 2002-04-22 14:52 ` Don Howard
2002-04-29 13:28 ` Jim Blandy
1 sibling, 1 reply; 5+ messages in thread
From: Don Howard @ 2002-04-22 14:52 UTC (permalink / raw)
To: Jim Blandy; +Cc: gdb
On Tue, 16 Apr 2002, Jim Blandy wrote:
>
> Could a C++ person check my understanding of `using namespace'
> directives?
>
> I'm reading Stroustrup, and the more I read about `using namespace',
> the weirder it gets. Check this out:
>
> namespace A
> {
> int x;
> int y;
> int z;
> };
>
> void f ()
> {
> int *x;
>
> {
> int *y;
> using namespace A;
>
> *x; /* `x' refers to local x, not A::x */
> *y; /* `y` refers to local y, not A::y */
> z; /* `z' refers to A::z */
> }
> }
This example seems correct to me, as the compiler can dis-ambiguate based
on type-- dereference works on pointers, so x and y must refer to the
local versions.
>
> This program is type-correct, so you can see exactly which definitions
> those identifiers refer to. I ran it through the newest GCC, and it
> didn't complain about ambiguities. Stroustrup C.10.1 agrees.
>
> Weird, huh? Although the `using namespace' directive does make A's
> variables visible, A's bindings are still *shadowed* by local
> variables in blocks that *enclose* the one containing the `using
> namespace' directive.
>
> So, here's the way I'd describe the effect of a `using namespace'
> directive:
>
> To look up some identifier X in a scope that has a `using namespace N'
> directive, search for both X and N::X. If you find more than one
> match, report an ambiguity. (But see below for a subtlety in the
> definition of an "ambiguity".)
>
> Now, suppose you've got nested compound statements. In the absence of
> namespaces, you start at the innermost enclosing block, and work your
> way out looking for a binding. In the presence of `using namespace'
> directives, you accumulate extra prefixes to search under as you go
> out.
>
> So in this case:
>
> namespace A
> {
> int x;
> int *y;
> };
>
> void
> f ()
> {
> using namespace A;
>
> {
> int *x;
>
> *x; /* `x' refers to local x */
> *y; /* `y' refers to A::y */
> }
> }
>
> Since B has no binding for x, the reference in `*x' refers to the
> local x, without ambiguity, even though A is `used' in an enclosing
> scope.
Again, the compiler can deduced this from type info.
>
> Regarding what constitutes an "ambiguity": if the same declaration
> makes it into a scope under two different names, that's not considered
> an ambiguity. So the compiler accepts the following without
> complaint.
>
> namespace A
> {
> int x;
> };
> namespace B
> {
> using A::x;
> };
>
> void
> f ()
> {
> using namespace A;
> using namespace B;
>
> x;
> }
>
> However, if we give namespace B its own `int x' definition, the
> compiler does complain.
>
> Is this all correct?
>
Makes sense to me. Stroustrup's chapter on namespaces has an example that
is similar to B above.
--
dhoward@redhat.com
gdb engineering
^ permalink raw reply [flat|nested] 5+ messages in thread* Re: C++ namespace using directives
2002-04-22 14:52 ` Don Howard
@ 2002-04-29 13:28 ` Jim Blandy
2002-04-29 14:30 ` Don Howard
0 siblings, 1 reply; 5+ messages in thread
From: Jim Blandy @ 2002-04-29 13:28 UTC (permalink / raw)
To: Don Howard; +Cc: gdb
Don Howard <dhoward@redhat.com> writes:
> On Tue, 16 Apr 2002, Jim Blandy wrote:
> > Could a C++ person check my understanding of `using namespace'
> > directives?
> >
> > I'm reading Stroustrup, and the more I read about `using namespace',
> > the weirder it gets. Check this out:
> >
> > namespace A
> > {
> > int x;
> > int y;
> > int z;
> > };
> >
> > void f ()
> > {
> > int *x;
> >
> > {
> > int *y;
> > using namespace A;
> >
> > *x; /* `x' refers to local x, not A::x */
> > *y; /* `y` refers to local y, not A::y */
> > z; /* `z' refers to A::z */
> > }
> > }
>
> This example seems correct to me, as the compiler can dis-ambiguate based
> on type-- dereference works on pointers, so x and y must refer to the
> local versions.
No, that's not what's going on at all. In Stroustrup's example, there
is no dereferencing going on, and he makes the same claims about which
binding each reference refers to as I do. I added the dereferences as
a sanity check, to make sure GCC was doing the right thing.
So you see why I think this behavior is way wacky? The `using
namespace' directive appears in the inner block, the local definition
appears in the outer block, but references to `x' in the inner block
still see the local definition in the outer block.
^ permalink raw reply [flat|nested] 5+ messages in thread* Re: C++ namespace using directives
2002-04-29 13:28 ` Jim Blandy
@ 2002-04-29 14:30 ` Don Howard
0 siblings, 0 replies; 5+ messages in thread
From: Don Howard @ 2002-04-29 14:30 UTC (permalink / raw)
To: Jim Blandy; +Cc: gdb
On 29 Apr 2002, Jim Blandy wrote:
>
> Don Howard <dhoward@redhat.com> writes:
> > On Tue, 16 Apr 2002, Jim Blandy wrote:
> > > Could a C++ person check my understanding of `using namespace'
> > > directives?
> > >
> > > I'm reading Stroustrup, and the more I read about `using namespace',
> > > the weirder it gets. Check this out:
> > >
> > > namespace A
> > > {
> > > int x;
> > > int y;
> > > int z;
> > > };
> > >
> > > void f ()
> > > {
> > > int *x;
> > >
> > > {
> > > int *y;
> > > using namespace A;
> > >
> > > *x; /* `x' refers to local x, not A::x */
> > > *y; /* `y` refers to local y, not A::y */
> > > z; /* `z' refers to A::z */
> > > }
> > > }
> >
> > This example seems correct to me, as the compiler can dis-ambiguate based
> > on type-- dereference works on pointers, so x and y must refer to the
> > local versions.
>
> No, that's not what's going on at all. In Stroustrup's example, there
> is no dereferencing going on, and he makes the same claims about which
> binding each reference refers to as I do. I added the dereferences as
> a sanity check, to make sure GCC was doing the right thing.
So the Stroustrup example looks like this:
namespace A
{
int x = 10;
int y = 20;
int z = 30;
};
int x = 100;
void f ()
{
int x = 0;
{
int y = 0;
using namespace A;
x = 1;
y = 2;
z = 42; // Which one is not like the others... This one.
printf ("A::x == %d\nA::y == %d\nA::z == %d\nx == %d\ny == %d\n::x == %d\n",
A::x, A::y, A::z, x, y, ::x);
}
}
int main (void)
{
f ();
}
....
franklinstower$ ./foo
A::x == 10
A::y == 20
A::z == 42
x == 1
y == 2
::x == 100
>
> So you see why I think this behavior is way wacky? The `using
> namespace' directive appears in the inner block, the local definition
> appears in the outer block, but references to `x' in the inner block
> still see the local definition in the outer block.
Yes, I expected the 'using namespace' directive to affect scoping rules
somehow, but that isn't what it does. Hmm. reading Stroustrup's reasoning
makes this more clear. He wanted to implement a backward compatable way
to partition namespaces -- one that would not require existing code to be
changed. To that end, the 'using namespace' directive is not a scope
resolution operator. The statement 'using namespace A' just makes the
members of A available to the local block at global (?) scope (does that
make sense?).
So the following doesn't compile due to ambiguity:
namespace A
{
...
int z;
}
int z;
...
{
using namespace A;
z = 42;
}
[And it I just found Gaby Dos Reis' response to your first mail, which
says just what I spent 30 minutes looking up...]
--
dhoward@redhat.com
gdb engineering
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2002-04-29 21:30 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2002-04-16 14:41 C++ namespace using directives Jim Blandy
2002-04-16 19:39 ` Gabriel Dos Reis
2002-04-22 14:52 ` Don Howard
2002-04-29 13:28 ` Jim Blandy
2002-04-29 14:30 ` Don Howard
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox