0

Here is the code example:

#include<iostream>
using namespace std;
namespace B
{
  int ohoh=2;
}

namespace A
{
  int ohoh=666;
  namespace C 
  {
      //using B::ohoh;(as if declared by using directive) //why does the lookup not stops here?
      int foo()
      {
        using namespace B;
        cout<<ohoh<<endl;
      }
  }
}

int main()
{
    A::C::foo();
}  

The output is 666 but not 2. Why?

Quoted from cppref

For an unqualified name, that is a name that does not appear to the right of a scope resolution operator ::, name lookup examines the scopes as described below, until it finds at least one declaration of any kind, at which time the lookup stops and no further scopes are examined. (Note: lookup from some contexts skips some declarations, for example, lookup of the name used to the left of :: ignores function, variable, and enumerator declarations, lookup of a name used as a base class specifier ignores all non-type declarations)

For the purpose of unqualified name lookup, all declarations from a namespace nominated by a using directive appear as if declared in the nearest enclosing namespace which contains, directly or indirectly, both the using-directive and the nominated namespace.

From the quoted paragraph above ,the name lookup should stop at nearest namespace C ,Where I've commented in the code.Why does it does not stop and find A::ohoh ?

By the way,I think I should use the using directive as little as possible.

Community
  • 1
  • 1
choxsword
  • 3,187
  • 18
  • 44

1 Answers1

6

For the purpose of unqualified name lookup, all declarations from a namespace nominated by a using directive as if declared in the nearest enclosing namespace which contains [...] both the using-directive and the nominated namespace.

In this case, the nearest namespace that contains both B and the using-directive is the global namespace. Therefore, all names from B appear inside A::C::foo as if they were declared in the global namespace. When searching for the name ohoh, A is searched before the global namespace, so A::ohoh is the first declaration found and name lookup stops there.

Miles Budnek
  • 28,216
  • 2
  • 35
  • 52
  • His commented statement is actually a using declaration – Passer By Mar 16 '18 at 05:37
  • I see,I used to think the nearest namespace is **C** – choxsword Mar 16 '18 at 05:38
  • @PasserBy From the question it sounds to me like that's there just for exposition. That's where the OP was thinking the name should be injected. It's possible I've misinterpreted the question though. – Miles Budnek Mar 16 '18 at 05:39
  • @PasserBy I just put that comment to show the nearest namespace from my understanding. – choxsword Mar 16 '18 at 05:39
  • @PasserBy And from what I've quoted,I think the "**as if declared**" has the same effect as `using declaration` ,which is aslo a declaration. – choxsword Mar 16 '18 at 05:40
  • @bigxiao `C` is the nearest enclosing namespace, but it does not contain both the nominated namespace (`B`) and the using-directive, so it is not the *nearest enclosing namespace which contains [...] both the using-directive and the nominated namespace* – Miles Budnek Mar 16 '18 at 05:41
  • @MilesBudnek So the compiler does not actually find `B::ohoh=2` ,does it? – choxsword Mar 16 '18 at 05:43
  • @bigxiao The *"as if declared"* is just loosely speaking, for the sake of explaining the name lookup rules. A using directive doesn't declare anything, otherwise you'd have a lot of redeclarations. – Passer By Mar 16 '18 at 05:43
  • @bigxiao It would if got to the global namespace, but the compiler stops searching when it finds `A::ohoh`. – Miles Budnek Mar 16 '18 at 05:45
  • @PasserBy I know that,but "as if" takes effect literally in the process of **name lookup** , and that's what the question is talking about. – choxsword Mar 16 '18 at 05:45