3.5. Namespaces

When we introduced functions, we noted that all functions are by default global. Another way of saying this is that they are by default in the global namespace. The namespace keyword provides a mechanism to avoid polluting the global namespace with too many names.

A namespace is simply a named block that defines a scope. Namespaces provide a method for preventing name conflicts in large projects.

Symbols declared inside a namespace block are placed in a named scope that prevents them from being mistaken for identically-named symbols in other scopes.

Multiple namespace blocks with the same name are allowed. All declarations within those blocks are declared in the named scope.

// declare some things in the mesa namespace
namespace mesa {
  int i = 0;
  double pi = 3.1416;
  void details (char);
}

void mesa::details (char c) { // define the function declared earlier
  // do something
}

//void mesa::oops () {       // error: oops not yet declared in mesa namespace
//}

namespace mesa {  // a separate mesa namespace block
  void oops ();
  namespace cisc {
    double pi = 3.14159265358979;  // not the same variable as mesa::pi
  }
}

int main () {
  using mesa::cisc::pi;
  pi = 3.f;
  mesa::details('a');
}

The larger your project, the more important it is to partition the global namespace. By default, all symbols are declared in the global namespace (::).

What is the problem with the global namespace?

Well-behaved third party libraries will not put much (if anything) in the global namespace.

You can put anything in a namespace, except main. The function main has a few special rules and one is that it must be in the global namespace.

The using directive allows all the names in a namespace to be used without the namespace-name as an explicit qualifier. Use a using directive in an implementation file (i.e. *.cpp) if you are using several different identifiers in a namespace; if you are just using one or two identifiers, then consider a using declaration to only bring those identifiers into scope and not all the identifiers in the namespace. If a local variable has the same name as a namespace variable, the namespace variable is hidden. It is an error to have a namespace variable with the same name as a global variable.

3.5.1. Prefer using declarations to using namespace std

What’s wrong with using namespace std;?

Nothing, technically. It was a simplification in your first semester classes. The intent was to avoid ‘burdening’ you with having to care about this technical detail.

BUT

The using-directive using namespace std; at any namespace scope introduces every name from the namespace std into the global namespace (since the global namespace is the nearest namespace that contains both std and any user-declared namespace), which may lead to undesirable name collisions. This, and other using directives are generally considered bad practice at file scope of a header file. Additionally, shadowing names in the standard namespace can lead to unexpected behaviors.

It can be hard to remember every name that might be imported when using namespace std;. Even when only 1 header is included.

The following example seems innocent enough, until you learn that showpoint is a name in std::ios

Run the following example twice, first as is, then remove the line bool showpoint = true;:

Errors using namespace directives are seldom this obviously wrong.

Here is a simplification of a real question asked on stack overflow:

This code compiles and runs and says the answer is: 0 1 -1 0. I think we can all agree that is not the correct answer for two points (0,0) and (100,100).

Try This!

What is wrong with the program?

Can you fix it?

Hint:

This section is about namespaces.

One final word from two experts:

Summary

Namespace usings are for your convenience, not for you to inflict on others: Never write a using declaration or a using directive before an #include directive.

Corollary: In header files, don’t write namespace-level using directives or using declarations; instead, explicitly namespace-qualify all names. (The second rule follows from the first, because headers can never know what other header #include might appear after them.)

Discussion

In short: You can and should use namespace using declarations and directives liberally in your implementation files after #include directives and feel good about it. Despite repeated assertions to the contrary, namespace using declarations and directives are not evil and they do not defeat the purpose of namespaces. Rather, they are what make namespaces usable.

—Herb Sutter and Andrei Alexandrescu, C++ Coding Standards


More to Explore

You have attempted of activities on this page