Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

name lookup question ("gotw 30")

0 views
Skip to first unread message

Mayuresh

unread,
Jul 27, 2008, 5:25:22 AM7/27/08
to
Hello,

I looked at this example while trying to understand name lookup :
http://www.gotw.ca/gotw/030.htm . (It is also present in this book -
"More exceptional c++")

As per the article, the recursive call to foo() below at line marked
with "//1" should be ambiguous. However, it is not. It always invokes
N2::foo leading to infinite recursion.

Further, if I replace "using namespace N1" with "using N1::foo" , then
it will call N1::foo . As per the article, this too should be
ambiguous.

Is it a compiler bug (vs 2008 and gcc 4.1) or am i misunderstanding
the article?

Thanks!!
Mayuresh.


---------------------------------------------------------------------------
#include<iostream>

namespace N1
{
void foo()
{
std::cout << "Invoked N1::foo\n";
}
}

namespace N2
{
void foo()
{
using namespace N1;
std::cout << "Invoked N2::foo\n";
foo(); //1

}
}

int main()
{
N2::foo();
}
---------------------------------------------------------------------

--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

ארינדם מוּחרג'י

unread,
Jul 27, 2008, 5:41:54 PM7/27/08
to
On Jul 27, 2:25 pm, Mayuresh <b166er....@gmail.com> wrote:
> Hello,
>
> I looked at this example while trying to understand name lookup :http://www.gotw.ca/gotw/030.htm. (It is also present in this book -

> "More exceptional c++")
>
> As per the article, the recursive call to foo() below at line marked
> with "//1" should be ambiguous. However, it is not. It always invokes
> N2::foo leading to infinite recursion.

There is no ambiguity here because there is no König lookup.

>
> Further, if I replace "using namespace N1" with "using N1::foo" , then
> it will call N1::foo . As per the article, this too should be
> ambiguous.
>
> Is it a compiler bug (vs 2008 and gcc 4.1) or am i misunderstanding
> the article?

Not a compiler bug. foo() in N1 (or N2) does not take any parameters.
Nor is a type defined in namespace N1, whose instance is being used in
the recursive call to foo in N2. So König lookup does not kick in
here.

>

Try the following modification:

#include<iostream>


namespace N1
{
struct X {};
void foo(X a)


{
std::cout << "Invoked N1::foo\n";
}
}


namespace N2
{
//using namespace N1;
void foo(N1::X b)
{


std::cout << "Invoked N2::foo\n";

foo(b); //1
}
}


int main()
{
N1::X a;
N2::foo(a);

Yechezkel Mett

unread,
Jul 28, 2008, 2:16:09 PM7/28/08
to
On Jul 27, 12:25 pm, Mayuresh <b166er....@gmail.com> wrote:
> Hello,
>
> I looked at this example while trying to understand name lookup :http://www.gotw.ca/gotw/030.htm. (It is also present in this book -

> "More exceptional c++")
>
> As per the article, the recursive call to foo() below at line marked
> with "//1" should be ambiguous. However, it is not. It always invokes
> N2::foo leading to infinite recursion.

The case under discussion:

namespace N1 {
void foo() {
std::cout << "Invoked N1::foo\n";
}
}

namespace N2 {
void foo() {
using namespace N1;
std::cout << "Invoked N2::foo\n";
foo(); //1
}
}

(Note all quotes taken from N2588 - a recent draft for C++0x, but I
doubt this has changed significantly)

7.3.4p2 says:
"""
2 A using-directive specifies that the names in the nominated
namespace can be used in the scope in which the using directive
appears after the using-directive. During unqualified name lookup
(3.4.1), the names appear as if they were declared in the nearest
enclosing namespace which contains both the using-directive and the
nominated namespace. [ Note: in this context, “contains” means
“contains directly or indirectly”. —end note ]
"""

Here the "nearest enclosing namespace" is the global namespace, so
N1::foo appears as if it is ::foo, and is hidden by N2::foo. (I think
I've understood this correctly.)

> Further, if I replace "using namespace N1" with "using N1::foo" , then
> it will call N1::foo . As per the article, this too should be
> ambiguous.

7.3.3p1 says
"""
A using-declaration introduces a name into the declarative region in
which the using-declaration appears. <snip> The member name specified
in a using-declaration is declared in the declarative region in which
the using-declaration appears.
"""

So N1::foo is declared as foo in the block scope, and hides N2::foo.

> Is it a compiler bug (vs 2008 and gcc 4.1) or am i misunderstanding
> the article?

I presume you are referring to the following paragraph in the article:
"""
There is another function with signature f(int), namely the one in
namespace A. If B had written "using namespace A;" or "using A::f;",
then A::f(int) would have been visible as a candidate when looking up
f(int), and the "f(i);" call would have been ambiguous between
A::f(int) and B::f(int). Since B did not bring A::f(int) into scope,
however, only B::f(int) is considered and so the call is unambiguous.
"""

He seems to mean putting the using-directive or using-declaration
directly in namespace B (the equivalent of your namespace N2), which
would certainly be true for the declaration (using A::f) because now
both f's are in the same scope and neither hides the other, but
according to my reading should not happen with the directive (using
namespace A) because then A::f appears as ::f and should be hidden.

Yechezkel Mett

Jiang

unread,
Jul 29, 2008, 1:01:36 AM7/29/08
to
On Jul 27, 6:25 pm, Mayuresh <b166er....@gmail.com> wrote:
> Hello,

[...]

The concept of scope, and the difference between namespace's
using-directive and using-declaration are the main points here.
Also, yes, this issue has nothing to do with the Koenig lookup.

> As per the article, the recursive call to foo() below at line marked
> with "//1" should be ambiguous.
> However, it is not. It always invokes
> N2::foo leading to infinite recursion.


It depends on how you introduce N1::foo. The following code
won't compile, for name ambiguous.

-------------------------------------------------

#include<iostream>

namespace N1
{
void foo(){std::cout << "Invoked N1::foo\n";}
}

namespace N2
{
using N1::foo; /// <- "A using-declaration"
void foo(){
std::cout << "Invoked N2::foo\n";
foo(); ///1
}
}

int main()
{
N2::foo();
}

-------------------------------------------------

Here, as Yechezkel Mett said, "using N1::foo;" is a
using-declaration, and it will introduce a name, here N1:foo
into the declarative region (inside N2). Therefore we have
two same functions within the same region/scope, which
causes ambiguous.

Also please note "using namespace N1" is a using-directive,
it does change/expand the select scope for the coming
name-lookup. However, in your original example, compilers
can select the best function according to the rules
Yechezkel Mett mentioned.

> Further, if I replace "using namespace N1" with "using N1::foo" , then
> it will call N1::foo . As per the article, this too should be
> ambiguous.

Yes, that the point for the difference between using-directive
and using-declaration. Furthermore, for the scope issue,

------------- just for explanation, won't compile--------------

#include<iostream>

namespace N1
{
void foo(){std::cout << "Invoked N1::foo\n";}
}

using N1::foo; /// <- "A using-declaration"
/// however, will be hidden by N2::foo
namespace N2
{
using N1::foo; /// <- "A using-declaration"
/// ambiguous, as explained above
void foo(){

using N1::foo; /// <- "A using-declaration"
/// will hide N2::foo

std::cout << "Invoked N2::foo\n";

foo(); ///1
}
}

int main()
{
N2::foo();
}

-------------------------------------------------


> Is it a compiler bug (vs 2008 and gcc 4.1) or am i misunderstanding
> the article?

Not a compiler bug. IMHO, "More Exceptional C++" needs full example
and better wording here, since this is a quite confusing topic.

You can Issue a "bug" report to Herb Sutter if you want. :-)
http://www.gotw.ca/publications/mxc++-errata.htm

Jiang

0 new messages