Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Nesting unnamed namespaces

Tags:

c++

namespaces

Is there a functional difference between these two nested usages of unnamed namespaces:

namespace A { namespace {
  void foo() {/*...*/}
}}

and

namespace { namespace A {
  void foo() {/*...*/}
}}

As far as I see it, both foos will get an internal unique identifier per compilation unit and can be accessed with A::foo - but is there a subtle or not-so-subtle difference that I'm not seeing?

like image 368
ltjax Avatar asked Jun 15 '11 13:06

ltjax


People also ask

What is unnamed namespace?

A namespace with no identifier before an opening brace produces an unnamed namespace. Each translation unit may contain its own unique unnamed namespace. The following example demonstrates how unnamed namespaces are useful.

What are nested namespaces?

A namespace inside a namespace is called a nested namespace in C#. This is mainly done to properly structure your code. We have an outer namespace − namespace outer {} Within that, we have an inner namespace inside the outer namespace − namespace inner { public class innerClass { public void display() { Console.

Can you nest namespaces C++?

In C++, namespaces can be nested, and resolution of namespace variables is hierarchical.

Can you use multiple namespaces C++?

You can have the same name defined in two different namespaces, but if that is true, then you can only use one of those namespaces at a time. However, this does not mean you cannot use the two namespace in the same program. You can use them each at different times in the same program.


1 Answers

Exactly as you typed, there is no difference.

You can, of course, add declarations in the first level of namespace to booth examples and then it will be a difference.

namespace A {
  int i;         // Accessed globally in this file as "A::i".
  namespace {
    void foo() {/*...*/}
}}


namespace {
  int i;         // Accessed globally in this file simply as "i".
  namespace A {
    void foo() {/*...*/}
}}}

Note that, although you programmer have no way to distinguish, for the compiler, the namespaces are distinct:

unnamed_namespaces.cpp:42:5: error: reference to ‘A’ is ambiguous
unnamed_namespaces.cpp:19:17: error: candidates are: namespace A { }
unnamed_namespaces.cpp:28:19: error:                 namespace <unnamed>::A { }

Usefull:

  • Nested anonymous namespace?
  • http://www.codingunit.com/cplusplus-tutorial-namespaces-and-anonymous-namespaces
  • http://publib.boulder.ibm.com/infocenter/comphelp/v8v101/index.jsp?topic=%2Fcom.ibm.xlcpp8a.doc%2Flanguage%2Fref%2Funnamed_namespaces.htm
  • http://www.informit.com/articles/article.aspx?p=31783&seqNum=6
  • http://msdn.microsoft.com/en-us/library/yct4x9k5%28v=vs.80%29.aspx

EDIT:

In respect to ADL (Argument-dependent name lookup), I understand that it will be no precedence difference in overload resolution for other foo() as below:

#include    <iostream>

void foo() { std::cout << "::foo()" << std::endl; }

namespace A {
    namespace {
        void foo() { std::cout << "A::<unnamed>::foo()" << std::endl; }

        class   AClass
        {
        public:
            AClass( )
            {   foo( ); }
        };
    }
}


namespace {
    namespace B {
        void foo() { std::cout << "B::<unnamed>::foo()" << std::endl; }

        using namespace A;

        class   BClass
        {
        public:
            BClass( )
            {   foo( ); }

            ~BClass( )
            {   A::foo( );  }
        };
    }
}

int main( )
{
    A::foo( );
    B::foo( );
    foo( );

    A::AClass   a;
    B::BClass   b;

    return  0;
}

Compiler will prefer the closest foo( ) unless explicitly specified. So BClass constructor calls B::foo( ) even having a using namespace A on it. To call A::foo( ) on BClass destructor, the call must be explicitly qualified.

A::<unnamed>::foo()
B::<unnamed>::foo()
::foo()
A::<unnamed>::foo()
B::<unnamed>::foo()
A::<unnamed>::foo()

Maybe it become clearer if we think in nested named namespaces and how the argument-dependent will be solved. The olny difference will be an implicit using on the unnamed ones, but it won't change the compiler preference.

like image 108
j4x Avatar answered Oct 11 '22 03:10

j4x