C++ Standard

Previous Next
6

Mysteries of Namespaces

Posted by Michael_Wong Feb 10, 2009

There are few features added in the last C++98 standardization that caused nearly all earlier C++ code to break. One is the addition of namespace and the moving of almost all of the C++ Standard library into it. Can you name a few examples that were not moved into standard namespace? This is the first Mystery of the Month.

Yet, used in its simplest way, namespaces are basically benign. A namespace is a subdivision of global scope. But even basic namespace as they are come with gotchas, which I will show in this discussion.

Next, we will take a closer look at using directives and declarations.

There are a number of key differences between these two. What are they and can you figure it out from the way this code behaves:

#include <vector>

int main()
{
using namespace std; //a using directive
int vector=99;
vector<int> x; 

}


and this
#include <vector>

int main()
{
using std::vector; //a using declaration
int vector=99;
vector<int> x; 

}


Call this the second Mystery of the Month. What is this code telling us about the real nature of these two kinds of usings (specifically, about where they are actually declared)?

Knowing this, it saids something about their usage style too. IN fact, is it really a good choice to use them the way I have,

1. inside a function body or
2. should I place them at file scope ahead of the include or
3. should I place them at file scope after the include or
4. should I place them in a header file

This is mystery number 3. Where should they be used and this one is necessarily somewhat subjective in one of the choice, but one is clearly evil. You just need to defend your choices.

Tags: c++, namespace


Feb 10, 2009 10:26 AM Click to view hstong's profile hstong

For mystery #1, aside from the C standard library macros, the operators new and delete in <new> come to mind.

Feb 10, 2009 10:51 AM Click to view Michael_Wong's profile Michael_Wong in response to: hstong

Yes, you are right. I am guessing there were just too much legacy associated with these to move them into another namespace.

Feb 18, 2009 10:29 AM Click to view JiChao's profile JiChao

For mystery #2, using declaration introduces the name to the current scope while using directive makes the name visible in the current scope.

So for the first code snippet, the definition of the integer vector hides the definition of vector in std. For the second code snippet, using declaration brings the name vector in to the local scope and the definition of the integer vector causes a conflict.

Feb 18, 2009 10:36 AM Click to view JiChao's profile JiChao

For mystery #3, I am not aware of any problem puting using declaration/directive in function scope. It is not a good iead to put them in the file scope of a header file though. Adding them in the header file will potentially pollute the declarative scope of any files including the header file. Puting them in header file ahead of include can cause more problem because the names brought in are now visible in all included files, which might cause conflict or change the semantics. It's generally better to use qualified name such as std::vector in header files.

Feb 19, 2009 1:48 AM Click to view Michael_Wong's profile Michael_Wong in response to: JiChao

Yes, that is correct. The using directive effectively makes the names available from the namespace, making them accessible without qualification. It also makes it as if they were declared at global scope, not at the scope of the using directive. So as a result, local names will hide the namespace names.
The names also remain in force until the end of the function body.

Using declaration is less forceful and provides a middle ground between explicit qualification, and bulldozing your namespace with all the names. A using declaration is an actual declaration, and any local names that are not the same type will lead to a redeclaration error. This is what you observed in the second code snippet.

From this discussion, it is pretty clear that a using-declaration requires that the name it declare must have already been seen. This makes a using-declaration order dependent when using names from a namespace split across a group of header files. This is potentially bad. The order of header inclusion relative to where the using-declaration appears is important and can change. Of course, the std namespace is one such namespace that is split across multiple headers.

So here is another difference with a using directive. Unlike a using-declaration, a using directive brings in names declared in namespaces both before and after the using directive. The name's declaration has to be still seen for it to be used, of course. This also makes using-directive powerful, and deadly in a different way then a using-declaration.

Feb 19, 2009 2:08 AM Click to view Michael_Wong's profile Michael_Wong in response to: JiChao

Nice work!

So from the answer to MOM#2, we can see that a using directive is like using a sledge hammer to your namespace, while a using declaration can be evil in that it depends on the order of includes.

I think I defintely agree that function scope is probably the best way to use it. The same goes for not ever putting either of them in header files. In one case, they bring in all kinds of names. In the other case, we have order dependency problems.

As for the middle two choices, either before or after the include in your CU, I would say definitely never use either of them before the #include. This is agreed by some noted authors.

As for after the include, I can't really think of a reason to discourage their use as long as it makes sense for your use.

C++ Standard

Bottom Banner