Abruzzo Forte e Gentile
Abruzzo Forte e Gentile

Reputation: 14879

namespaces having unnamed namespace with the same variable declared

I tried this dummy code below to test unnamed namespace.

I have the following output

 ctor 1
 ctor 0
 3
 5

I am a bit confused about this.

  1. I was expecting an error from the compiler saying that it cannot resolve an ambiguity regarding a::m_a. Instead it refers always to the less nested. Is it always the case? What rules C++ is following?
  2. It seems that the compiler creates variable CMyObj following the order written on the file. Is this always the case?
  3. is there any way to access the most nested m_a variable from main()?.
class CMyObj{     
    public:
    CMyObj(int a){std::cout  << "ctor " << a << std::endl; }
 };
 namespace a{ 
      namespace{
           int m_a=4;
           int m_b=5;
           CMyObj m_obj(1);
      }  
 }
 namespace a{
      int m_a=3;
      CMyObj m_obj(0);
 }
 int main(){
      std::cout << a::m_a << std::endl; // which one?
      std::cout << a::m_b << std::endl; // how this is possible?
      return 0;
 }

Upvotes: 7

Views: 322

Answers (4)

memecs
memecs

Reputation: 7574

There is no ambiguity because the scope of namespace::<unnamed>::m_a is the outer namespace (namespace::a). There is no way to access namespace::<unnamed>::m_a within the main function and that is why there is no ambiguity. Try the to compile the following code and you'll get the error:

namespace ns{
  namespace {
    int a = 2;
  }
  int a = 3;
  int c = a;
}

Global variables residing in the same translation unit will be initialized in the order they are declared. Initialization order of global variables declared in different translation units is undefined.

Upvotes: 0

Michael Mathews
Michael Mathews

Reputation: 382

I should take time to find the exact definitions in the spec, but when you have an anonymous (unnamed) namespace, the compiler actually generates a mangled name. When you write

a::m_b 

in the second std::cout statement, the compiler is automatically substituting the mangled name so you can access it. Incorporating from Gene Bushuyev's subsequent answer:

Now, remember that unnamed namespace is a uniquely named namespace with a using directive.

In the case of the colliding names, the compiler knows what a::m_a means, so it uses that. It's the one at the top level of the namespace. I don't think there is any way to get to the unnamed namespace copy of m_a at this point.

This page does a decent job of explaining namespaces. Winterdom: On C++ Namespaces

Upvotes: 1

GManNickG
GManNickG

Reputation: 504303

First look at this simplified code (and my simplified explanation, you can read §3.4.3.2 for the details):

namespace a
{
    int x;
}

int main()
{
    int i = a::x;
}

Consider what happens when we say a::x. First the compiler enumerates all the declarations of x in a. If it finds an unambiguous x, it finishes successfully. Otherwise it recursively searches the namespaces declared by a using-directive. If it never finds a result, the program is ill-formed.

namespace a
{
    int x;
}

namespace b
{
    using namespace a;
}

int main()
{
    int i = b::x;
}

Here, it doesn't find x in b, so it searches the namespace a (because of the using-directive) and finds it. It should now make sense why this isn't ambiguous:

namespace a
{
    int x;
}

namespace b
{
    using namespace a;
    int x;
}

int main()
{
    int i = b::x;
}

Here it finds the x in b and never considers a. Now just consider that an unnamed namespace is actually just a namespace with a unique unknown name:

namespace b
{
    namespace
    {
        int x;
    }

    // this is what an unnamed namespace expands to (in exposition)
    namespace __unique__ {}
    using namespace __unique__;

    namespace __unique__
    {
        int x;
    }

    int x;
}

int main()
{
    int i = b::x;
}

Like before, the x in b is found without considering the unnamed namespace. Your code is similar.

Upvotes: 1

Gene Bushuyev
Gene Bushuyev

Reputation: 5538

I don't have C++03 standard with me to check the wording there, so I will quote from FDIS n3290. I think the answer to this question is found in qualified name lookup rules in 3.4.3.2/2:

For a namespace X and name m, the namespace-qualified lookup set S(X,m) is defined as follows: Let S0(X,m) be the set of all declarations of m in X and the inline namespace set of X (7.3.1). If S0(X,m) is not empty, S(X,m) is S0(X,m); otherwise, S(X,m) is the union of S(Ni,m) for all namespaces Ni nominated by using-directives in X and its inline namespace set.

Now, remember that unnamed namespace is a uniquely named namespace with a using directive.

Upvotes: 3

Related Questions