Jump to content

  • Log In with Google      Sign In   
  • Create Account

anonymous namespaces : should they be used?


Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

  • You cannot reply to this topic
17 replies to this topic

#1 random_thinker   Members   -  Reputation: 282

Like
0Likes
Like

Posted 10 September 2007 - 11:11 PM

In Modern C++ Design (Alexandrescu), an example implementation of an object factory wraps a concrete object creator function and an ID in an anonymous namespace, to hide it from the rest of the programme. This practice, although effective, just seems inherently strange to me, but maybe this is a lack of experience on my part. Instinctively, I do not see why this could not be wrapped in a class instead, which is one of the purposes of a class or struct, to encapsulate and isolate the data and methods. Is it somehow safer to use anonymous namespaces? Is it more efficient when compared to alternatives? Are there situations where there is no choice? Any views? --random Edit--here is a simple example that illustrates my concern:
#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]

Sponsor:

#2 ToohrVyk   Members   -  Reputation: 1591

Like
1Likes
Like

Posted 11 September 2007 - 12:11 AM

Anonymous namespaces and global variables are completely orthogonal concepts. Anonymous namespaces restrict an identifier to a single file, while global variables allow global access through a given identifier. You can have a global variable in an anonymous namespace (usable in that file only) or at file scope (usable in all files), just like you can have a class or function in an anonymous namespace.

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).

#3 random_thinker   Members   -  Reputation: 282

Like
0Likes
Like

Posted 11 September 2007 - 12:34 AM

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?

--random

#4 ToohrVyk   Members   -  Reputation: 1591

Like
0Likes
Like

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 random_thinker   Members   -  Reputation: 282

Like
0Likes
Like

Posted 11 September 2007 - 01:21 AM

Oh I see...so then this code:


// 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 Bregma   Crossbones+   -  Reputation: 5498

Like
0Likes
Like

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 random_thinker   Members   -  Reputation: 282

Like
0Likes
Like

Posted 11 September 2007 - 01:53 AM

So let me see if I understand the use...in a practical sense, where a class or other operation needs certain supporting classes, functions and data that are not to be used by any other part of the programme, then these can be wrapped in an unnamed namespace within the same translation unit, and these will be found within that translation unit during the compile phase, but will not be found by the linker. Is that correct?

--random


#8 legalize   GDNet+   -  Reputation: 111

Like
0Likes
Like

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 free book on Direct3D: "The Direct3D Graphics Pipeline"
My blog on programming, vintage computing, music, politics, etc.: Legalize Adulthood!


#9 ToohrVyk   Members   -  Reputation: 1591

Like
0Likes
Like

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 SiCrane   Moderators   -  Reputation: 9675

Like
0Likes
Like

Posted 11 September 2007 - 05:31 AM

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.

#11 rip-off   Moderators   -  Reputation: 8763

Like
0Likes
Like

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 random_thinker   Members   -  Reputation: 282

Like
0Likes
Like

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 legalize   GDNet+   -  Reputation: 111

Like
0Likes
Like

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 free book on Direct3D: "The Direct3D Graphics Pipeline"
My blog on programming, vintage computing, music, politics, etc.: Legalize Adulthood!


#14 legalize   GDNet+   -  Reputation: 111

Like
0Likes
Like

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 free book on Direct3D: "The Direct3D Graphics Pipeline"
My blog on programming, vintage computing, music, politics, etc.: Legalize Adulthood!


#15 ToohrVyk   Members   -  Reputation: 1591

Like
0Likes
Like

Posted 11 September 2007 - 06:02 AM

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.

#16 SiCrane   Moderators   -  Reputation: 9675

Like
0Likes
Like

Posted 11 September 2007 - 06:36 AM

Ok, let's pretend you want to embed a string as a non-type template parameter.

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 random_thinker   Members   -  Reputation: 282

Like
0Likes
Like

Posted 11 September 2007 - 06:59 AM

Right...so...


// 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 legalize   GDNet+   -  Reputation: 111

Like
0Likes
Like

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 free book on Direct3D: "The Direct3D Graphics Pipeline"
My blog on programming, vintage computing, music, politics, etc.: Legalize Adulthood!





Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.



PARTNERS