unnamed namespace within named namespace
Asked Answered
H

6

28

Some code I've been asked to modify looks rather like this:

namespace XXX {

namespace {

// some stuff

} // end of unnamed

// Some stuff within the scope of XXX

} // end of XXX

I'm struggling to see the advantage, if any, of embedding the unnamed namespace within another namespace and I'm considering changing it to:

namespace {

// some stuff

} // end of unnamed

namespace XXX {

// Some stuff within the scope of XXX

} // end of XXX

Any views would be gratefully appreciated.

Holliholliday answered 7/1, 2013 at 17:31 Comment(0)
S
10

Okay, turns out that X::<anonymous>::foo() is visible as X::foo(). I'm surprised.

So, no, there's very little practical benefit. There may be semantic or documentation implications though.


Original answer

Well that rather depends on the "stuff", doesn't it?

The existing code allows code in X to have "private" other stuff that's also in X but cannot be accessed from outside of X:

#include <iostream>

namespace X {
   namespace {
      void foo() { std::cout << "lol\n"; }
   }
   
   void bar() { foo(); }
}

int main()
{
   X::bar();
   // X::foo();  // can't do this directly  [edit: turns out we can!]
}
  • Output: lol\n

Your proposed approach makes that "private stuff" available to the entire translation unit:

#include <iostream>

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

namespace X {
   void bar() { foo(); }
}

int main()
{
   X::bar();
   foo();     // works
}
  • Output: lol\nlol\n
Spurlock answered 7/1, 2013 at 17:32 Comment(13)
I see what you're getting at. What I should have made clear is that the only namespace in the translation unit is X so I don't think it makes a difference. If there were other namespaces or main I can understand it although to be honest in that case, I'd argue to rearrange the code translation units a bit. Thanks.Holliholliday
"So, no, there's very little practical benefit.". There is practical benefit. Names from the unnamed namespace cannot be accessed from other translation unit, even though they've external linkage, unless they're declared static or const.Emmaline
@Nawaz: ... which is the case for both the original code and the OP's suggested new code. And is therefore not a factor under consideration.Spurlock
@LightnessRacesinOrbit: Yes. But I was merely commenting on your statement, especially when it comes immediately after posting the link to ideone.com; I think you're drawing some conclusion from your ideone code.Emmaline
@Nawaz: I was answering the question :PSpurlock
@LightnessRacesinOrbit: I don't see any relation between the ideone code and that statement. :PEmmaline
@Nawaz: I tried out the same code of LightnessRacesinOrbit. and I was able to access X::foo() directly, even though foo() was defined in a nested anonymous namespace.Policlinic
Or is it because the main() is defined in the same compilation unit as the namespace stuff is?Policlinic
@abhinav: Yes, because you're accessing it from same translation(compilation) unit.Emmaline
This answer has been provided a long time ago and in my opinion it is wrong. In your first example you are assuming that main() and X::foo() reside in the same TU, so of course calling X::foo() in main() works. Also there is actually a huge benefit: You can still put stuff in named namespaces, but provide static linkage. A different TU will not be able to access X::foo(), while foo still (logically) pertains to namespace X. The second example puts foo() into global scope, which is very different from A::foo() and may lead to name clashes etc. (let alone the lost semantics).Radiator
@Radiator "The second example puts foo() into global scope," No, it doesn't.Spurlock
Does "into global namespace" sound better to you? And do you still argue that it has no benefit?Radiator
@Radiator No, that's just rewording the same false claim. The symbol is in an unnamed namespace, not the global namespace. / That bit aside, as far as I can tell, you're saying that the benefit is that your TU-local, unnamed-namespace foo is still "logically" inside X, and I won't argue with that, but it's not a bit benefit, and I said all of that in my answer's second paragraph!Spurlock
I
23

It does have practical benefit. An unnamed namespace hide names inside it from different translation units.

The above code works only because the definition of foo is in the same translation unit.

Suppose main() and the definition of foo() are in different translation unit. It would compile, since the main file include the header of the declaration. but it wouldn't link because logically there's no such thing as X::(unnamed namespace)::foo.

Injury answered 7/1, 2013 at 18:23 Comment(3)
This is the case for both examples. Thus, you are not describing the difference, nor the benefit of one over the other.Spurlock
@LightnessRacesinOrbit: The difference/benefit is the way you call it. With the proposed (top) way, you'd call XXX::some_function(); while with your proposal you'd have to call it like some_function(); It may be the case that calling without the XXX:: may be more error prone because you may accidentally call an external function from the global scope.Celindaceline
@GrimFandango I'm aware of that - the answer should explain it though. My comment was a criticism of the answer, not a request for help.Spurlock
S
10

Okay, turns out that X::<anonymous>::foo() is visible as X::foo(). I'm surprised.

So, no, there's very little practical benefit. There may be semantic or documentation implications though.


Original answer

Well that rather depends on the "stuff", doesn't it?

The existing code allows code in X to have "private" other stuff that's also in X but cannot be accessed from outside of X:

#include <iostream>

namespace X {
   namespace {
      void foo() { std::cout << "lol\n"; }
   }
   
   void bar() { foo(); }
}

int main()
{
   X::bar();
   // X::foo();  // can't do this directly  [edit: turns out we can!]
}
  • Output: lol\n

Your proposed approach makes that "private stuff" available to the entire translation unit:

#include <iostream>

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

namespace X {
   void bar() { foo(); }
}

int main()
{
   X::bar();
   foo();     // works
}
  • Output: lol\nlol\n
Spurlock answered 7/1, 2013 at 17:32 Comment(13)
I see what you're getting at. What I should have made clear is that the only namespace in the translation unit is X so I don't think it makes a difference. If there were other namespaces or main I can understand it although to be honest in that case, I'd argue to rearrange the code translation units a bit. Thanks.Holliholliday
"So, no, there's very little practical benefit.". There is practical benefit. Names from the unnamed namespace cannot be accessed from other translation unit, even though they've external linkage, unless they're declared static or const.Emmaline
@Nawaz: ... which is the case for both the original code and the OP's suggested new code. And is therefore not a factor under consideration.Spurlock
@LightnessRacesinOrbit: Yes. But I was merely commenting on your statement, especially when it comes immediately after posting the link to ideone.com; I think you're drawing some conclusion from your ideone code.Emmaline
@Nawaz: I was answering the question :PSpurlock
@LightnessRacesinOrbit: I don't see any relation between the ideone code and that statement. :PEmmaline
@Nawaz: I tried out the same code of LightnessRacesinOrbit. and I was able to access X::foo() directly, even though foo() was defined in a nested anonymous namespace.Policlinic
Or is it because the main() is defined in the same compilation unit as the namespace stuff is?Policlinic
@abhinav: Yes, because you're accessing it from same translation(compilation) unit.Emmaline
This answer has been provided a long time ago and in my opinion it is wrong. In your first example you are assuming that main() and X::foo() reside in the same TU, so of course calling X::foo() in main() works. Also there is actually a huge benefit: You can still put stuff in named namespaces, but provide static linkage. A different TU will not be able to access X::foo(), while foo still (logically) pertains to namespace X. The second example puts foo() into global scope, which is very different from A::foo() and may lead to name clashes etc. (let alone the lost semantics).Radiator
@Radiator "The second example puts foo() into global scope," No, it doesn't.Spurlock
Does "into global namespace" sound better to you? And do you still argue that it has no benefit?Radiator
@Radiator No, that's just rewording the same false claim. The symbol is in an unnamed namespace, not the global namespace. / That bit aside, as far as I can tell, you're saying that the benefit is that your TU-local, unnamed-namespace foo is still "logically" inside X, and I won't argue with that, but it's not a bit benefit, and I said all of that in my answer's second paragraph!Spurlock
R
10

Very little benefit from the global point of view: if viewed from other translation units' point of view, both approaches have same results: the anonymous namespace is invisible (or can't be referenced).

From the same translation unit point of view, there's a difference: The fact that you're defining a toplevel namespace means that you reduce the probability of importing a namespace conflict declared elsewhere, and the most common one would be for the global namespace (namespaceless functions, think of anything inherited from ISO C like from stdio.h or whatever).

For instance, if a global header you import in that translation unit had a "namespaceless" abort() and you declare a namespace { abort() { ...} } in your translation unit, you would have an ambiguity, gcc for instance would throw a compile error:

error: call of overloaded ‘abort()’ is ambiguous

Now, if you name an anonymous namespace inside a named namespace, you have these effects:

a) there's no ambiguity for functions declared inside the namespace, because it has precedence:

namespace a { namespace { abort() {...} } }

if you have a function like a::whatever() and it references abort(), it'll resolve at it's own namespace as it has precedence.

b) You won't have global linkage for a::abort() as it doesn't exist outside the translation unit, the same as namespace { abort(); } in the toplevel but without the potential conflict above.

And in "b" lies the difference: it's not the same as just namespace a { abort(); } because it won't have global linkage, so you could redefine it in another translation unit without conflicts. Good luck trying to link two translation units that both define namespace a { abort() { ... } } ...

So you get exactly as you mean:

namespace a { // you have a named space, so you don't have conflicts with the nameless one
  namespace { // but you have local visibility and linkage
    whatever(); // for this
  }
}

To put in short: both ways have similarities but there's a difference. One could argue that's not very useful, but as a style it'll preemptively avoid collisions with the global namespace. One can still argue that since these would be caught at compile time (hopefully, at least when signatures matches perfectly), why bother. But it's a useful concept if your project is a library meant to be portable and your headers could get polluted depending on whatever the environment headers themselves imports, for otherwise your users would have to patch your library for their systems or you'd need #ifdefs here and there.

I program a lot on ISO/ANSI C 99 and from times to times I have to do stuff like:

#include <headerA.h>
#define symbol symbolB
#include <headerB.h>
// or some crap alike. And I have linker problems with above.

... because both headers (from e.g. different libraries) manage to pollute the namespace and I can't simply patch someone else's library.

C++ namespace resolves that, except when somebody else don't use it, so you must take measures either to prevent (which isn't an option for legacy code) or to counteract it.

Rabbet answered 31/3, 2015 at 12:37 Comment(0)
R
4

One of the benefits of using unnamed namespace inside named namespace is to prevent Argument dependent lookup (ADL). Indeed, if you define types and functions in the same named namespace, you might encounter undesirable effects. The following example illustrate the problem :

Let's say we have a simple header file as below, where we define a generic function myfunction for our custom type mytype inside our namespace mynamespace.

//header.h
namespace mynamespace {
    struct mytype {};

    static void myfunction(mytype){}
}

Now, inside another file test.cpp, we want to override myfunction for a specific purpose (e.g. print debug info, do extra stuff, I18N...), without changing the rest of our program. The following code will not conflict with our header file because it is a different namespace i.e. the global namespace.

//test.cpp
#include "header.h"

static void myfunction(mynamespace::mytype){}

int main(){
    mynamespace::mytype val = {};
    //error: call of overloaded 'myfunction(mynamespace::mytype&)' is ambiguous
    myfunction(val);
}

Surprisingly, the call to myfunction above is ambiguous and does not compile, because of ADL. To solve your issue, you can prevent ADL thanks to anonymous namespace.

//header.h
namespace mynamespace {
    struct mytype {};

    //OK prevents ADL
    namespace {
        static void myfunction(mytype){}
    }
}
Ralleigh answered 22/10, 2019 at 15:16 Comment(0)
B
1

A simple benefit is that from the anonymous namespace within the named namespace, one can access directly things of the named namespace:

namespace foo {
    class Bar;

    namespace {
        void Baz() {
            Bar bar;  // no need to specify the foo namespace 
            …
        }
    }

    …
}

instead of:

class foo::Bar;

namespace {
    void Baz() {
        foo::Bar bar;
        …
    }
}

namespace foo {
    …
}
Breathing answered 30/12, 2021 at 19:6 Comment(0)
S
0

Placing an anonymous namespace within a named namespace can help to reduce a chance of collisions with unity builds.

The following doesn't compile due to redefinition of ‘void {anonymous}::foo()’:

ns1.cpp:

#include <iostream>

namespace
{
    void foo()
    {
        std::cout << "I'm private ns1.cpp:foo." << std::endl;
    }
}

namespace ns1
{

    void bar()
    {
        foo();
    }
}

ns2.cpp:

#include <iostream>

namespace
{
    void foo()
    {
        std::cout << "I'm private ns2.cpp:foo." << std::endl;
    }
}

namespace ns2
{

    void bar()
    {
        foo();
    }
}

unity.cpp:

#include "ns1.cpp"
#include "ns2.cpp"

int main() {
    ns2::bar();
}

Placing the anonymous namespace containing foo() into a named namespace avoids this issue and the code compiles and runs as expected producing I'm private ns2.cpp:foo..

ns1.cpp:

#include <iostream>

namespace ns1
{
    namespace
    {
        void foo()
        {
            std::cout << "I'm private ns1.cpp:foo." << std::endl;
        }
    }

    void bar()
    {
        foo();
    }
}

ns2.cpp

#include <iostream>

namespace ns2
{
    namespace
    {
        void foo()
        {
            std::cout << "I'm private ns2.cpp:foo." << std::endl;
        }
    }

    void bar()
    {
        foo();
    }
}

unity.cpp - same as above

Sensational answered 25/3, 2024 at 18:16 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.