#include <iostream.h>
namespace
{
int local; // should not collide with other files
}
void func()
{
local = 2;
}
int main()
{
local = 1;
cout<< "local=" << local << endl;
func();
cout<< "local=" << local << endl;
return 0;
}
// results in
local=1
local=2
Is there any difference between unnamed namespaces and globals?
[Edited by - random_thinker on September 11, 2007 5:48:23 AM]
anonymous namespaces : should they be used?
#1 Members - Reputation: 282
Posted 10 September 2007 - 11:11 PM
#2 Members - Reputation: 1583
Posted 11 September 2007 - 12:11 AM
The advantages of anonymous namespaces are that you don't have link-time collisions (because your identifiers are restricted to a single file) and don't pollute headers with implementation details (like a static class member or nested class would).
#4 Members - Reputation: 1583
Posted 11 September 2007 - 12:58 AM
Quote:
Original post by random_thinker
So in the above code, in theory, if I separated the anonymous namespace to another file, I should get an error when I try to compile?
To another translation unit, yes. However, the main purpose is (as mentioned before) related to linking, not compiling.
#5 Members - Reputation: 282
Posted 11 September 2007 - 01:21 AM
// contents of main.cpp
#include <iostream>
int nfunc();
int func()
{
return 1;
}
int main()
{
using namespace std;
cout<< "local=" << func() << endl;
cout<< "local=" << nfunc() << endl;
return 0;
}
// contents of nspace.cpp
namespace
{
int func()
{
return 2;
}
}
int nfunc()
{
return func();
}
Will return:
local=1
local=2
and the linker will not see the symbol func() twice. I guess that unnamed namespaces are a good practice where needed.
thx!
--random
#6 Members - Reputation: 2762
Posted 11 September 2007 - 01:52 AM
Quote:
Original post by random_thinkerIs there any difference between unnamed namespaces and globals?
Well, "globals" are namespace-level names in the global namespace. The global namespace is a namespace just like any other. It has no spcial properties and participates in overload resolution just like any other namespace.
That means names in an anonymous namespace, in the current namespace, in the global namespace, and in any namespaces currently in scope due to a "using" directive all participate equally in name resolution.
The big difference is when it comes to name conflicts. With a regular namespace (a named namespace or the global namespace) you can always disambiguate by fully qualifying the name with the namespace (eg. ::func1() for a global variable). You cannot do this with the anonymous namespace. There is no way to disambiguate names declared in an anonymous namespace.
Like many tools, this gives you increased power (of protection) at a known cost (inability to disambiguate).
Me, I've learned to use anonymous namespaces frequently. I've been burned too many times having to support an undocumented API. C-with-classes programmers, although evidently in the majority, are not altogether the bunch leading the human race forwards.
#7 Members - Reputation: 282
Posted 11 September 2007 - 01:53 AM
--random
#8 GDNet+ - Reputation: 106
Posted 11 September 2007 - 05:24 AM
Quote:
Original post by ToohrVyk
The advantages of anonymous namespaces are that you don't have link-time collisions (because your identifiers are restricted to a single file) and don't pollute headers with implementation details (like a static class member or nested class would).
Interesting. I never mucked around with anonymous namespaces. How is it different from declaring the variable static, which also limits its scope to a single file?
My blog on programming, vintage computing, music, politics, etc.: Legalize Adulthood!
#9 Members - Reputation: 1583
Posted 11 September 2007 - 05:30 AM
Quote:
Original post by legalize
Interesting. I never mucked around with anonymous namespaces. How is it different from declaring the variable static, which also limits its scope to a single file?
It also works with classes and structures, for instance defining two distinct Visitor classes in two different files without the linker doing strange things with them (the sad part about these collisions is that you don't get a 'multiple definition' error, but rather the behaviour of the binary is erratic).
#10 Moderators - Reputation: 6640
Posted 11 September 2007 - 05:31 AM
#11 Moderators - Reputation: 5034
Posted 11 September 2007 - 05:32 AM
Quote:
Original post by legalize Quote:
Original post by ToohrVyk
The advantages of anonymous namespaces are that you don't have link-time collisions (because your identifiers are restricted to a single file) and don't pollute headers with implementation details (like a static class member or nested class would).
Interesting. I never mucked around with anonymous namespaces. How is it different from declaring the variable static, which also limits its scope to a single file?
Well, anonymous namespaces are supposed to be used in favour of this use of "static", or so I thought until recently. But one thread made me question this, as they don't seem to map to each other completely. Read more here.
[edit:]
Quote:
Original post by SiCrane
Definitions inside a anonymous namespace can still have external linkage, while they don't cause name collisions at link time. This is important for template types which require names with external linkage for certain template parameters.
Ok, thanks that explains it. [smile]
#12 Members - Reputation: 282
Posted 11 September 2007 - 05:43 AM
Quote:
Well, anonymous namespaces are supposed to be used in favour of this use of "static", or so I thought until recently. But one thread made me question this, as they don't seem to map to each other completely. Read more here.
[edit:]Quote:
Original post by SiCrane
Definitions inside a anonymous namespace can still have external linkage, while they don't cause name collisions at link time. This is important for template types which require names with external linkage for certain template parameters.
Ok, thanks that explains it. [smile]
Stroustrup specifically forbids the use of static at global or file scope (only recommending it for class/struct or function scope), and recommends the use of unnamed namespaces instead.
As I usually ask Si, do you have a simple example of unnamed namespace (external linkage) combined with template usage? I learn more from studying your examples than a month's worth of class time.
--random
#13 GDNet+ - Reputation: 106
Posted 11 September 2007 - 05:46 AM
Quote:
Original post by ToohrVyk Quote:
Original post by legalize
Interesting. I never mucked around with anonymous namespaces. How is it different from declaring the variable static, which also limits its scope to a single file?
It also works with classes and structures, for instance defining two distinct Visitor classes in two different files without the linker doing strange things with them (the sad part about these collisions is that you don't get a 'multiple definition' error, but rather the behaviour of the binary is erratic).
This would be true of functions, classes and structures declared static as well, so I don't think that's the defining difference.
My blog on programming, vintage computing, music, politics, etc.: Legalize Adulthood!
#14 GDNet+ - Reputation: 106
Posted 11 September 2007 - 05:51 AM
Quote:
Original post by SiCrane
Definitions inside a anonymous namespace can still have external linkage, while they don't cause name collisions at link time. This is important for template types which require names with external linkage for certain template parameters.
OK, I can see the difference here, but I don't see the value yet... I consider myself pretty proficient in C++, but I haven't yet become a "meta programming" guru with all the template stuff. Hell, its been a hard enough slog to get my coworkers to use the standard library...
My blog on programming, vintage computing, music, politics, etc.: Legalize Adulthood!
#16 Moderators - Reputation: 6640
Posted 11 September 2007 - 06:36 AM
template <const char * string>
std::string bar(void) {
return string;
};
int main(int, char **) {
std::cout << bar<"Hello">(); // this is illegal; string literals have internal linkage
return 0;
}
So one way to get that to compile is to declare a const char array with external linkage.
extern const char message[] = "Hello";
int main(int, char **) {
std::cout << bar<message>();
return 0;
}
However, now you've got an exported symbol message that could cause collisions with other translation units, so if you stick it in an anonymous namespace you eliminate the possible collision.
#17 Members - Reputation: 282
Posted 11 September 2007 - 06:59 AM
// File 'Main.cpp'
template <const char * string>
std::string bar(void)
{
return string;
};
namespace
{
extern const char message[] = "Hello";
}
int main(int, char **)
{
std::cout << bar<message>() << std::endl;
return 0;
}
// File 'World.cpp"
extern const char message[] = " World";
after build and execution, results in:
Hello
I see....
Thx,
--random
#18 GDNet+ - Reputation: 106
Posted 11 September 2007 - 08:46 AM
Quote:
Original post by ToohrVyk Quote:
Original post by legalize
This would be true of functions, classes and structures declared static as well, so I don't think that's the defining difference.
You cannot declare a class or structure as static.
Ah, good point. You can create a static instance of a class or struct, but you can't limit its visibility to a single compilation unit without making it "nameless" and static, i.e.
static struct
{
int foo;
int bar;
} foobar;
My blog on programming, vintage computing, music, politics, etc.: Legalize Adulthood!






