Namespaces
Variants
Views
Actions

Namespaces in C++

From cppreference.com


In C++, all identifiers in the global scope must be unique. This may become a problem, especially in larger projects where a programmer uses a lot of components from different libraries. In such cases there's high chance that two components will have the same name in two different libraries, a situation called name collision or conflict. This makes impossible to use those libraries together.

In C and some other languages this problem is solved by adding a specific prefix to the names of all identifiers in a specific library. This guarantees that there are no equal identifiers in any two libraries. Unfortunately this increases the length of the identifiers and thus reduces readability and convenience of programming.

Namespaces are an elegant solution to the problem. Instead of an immutable prefix to the identifier names, namespaces introduce a new, named scope. From within the namespace, all identifiers are referenced as usual. However, if one wants to refer to the identifiers from outside the namespace, the namespace prefix nmname:: must be prepended, where nmname is the name of the namespace. See the example below:

#include <iostream>
 
namespace yyy {
 
void baz() { std::cout << "baz\n"; }
void foo() { baz(); } // no need to append the name of the namespace
 
} // namespace yyy
 
namespace zzz {
 
void foo() { std::cout << "foo\n"; }
 
} // namespace zzz
 
int main()
{
    yyy::foo(); // Both functions can be called, even though
    zzz::foo(); // they have the same name
}

Output:

baz
foo

Note that the // namespace yyy comments are not required, they are only there only for clarity.

Contents

[edit] Syntax

[edit] Nested namespaces

[edit] Importing a namespace

One of the features of a namespace is that it's possible to remove the namespace prefix to save a bit of typing. The basic syntax of a namespace import declaration is as follows:

using namespace nmspace_name;

After such declaration, all names that we would otherwise have referred as nmspace_name::identifier can be used simply as identifier.

#include <iostream>
 
namespace yyy {
namespace zzz {
void baz() { std::cout << "baz"; }
} // namespace zzz
 
using namespace zzz;
 
void foo()
{
    baz();       // Can use baz without zzz::
    zzz::baz();  // Still can use baz explicitly
}
 
} // namespace yyy
 
using namespace yyy;
 
int main()
{
    yyy::foo();   // explicit cal
    foo();        // yyy was imported
 
    // The following four call the same function via different path
 
    yyy::zzz::baz();  // Explicit call, this would be needed if we didn't 
                      // import the namespaces
    zzz::baz();   // The contents of namespace yyy were imported into the global namespace
    yyy::baz();   // The contents of namespace zzz were imported into the yyy namespace
    baz();        // baz was imported into yyy and then into the global namespace 
    std::cout << "\n";
}

Output:

bazbazbazbazbazbaz

[edit] Alias

The verbosity of namespaces can be an advantage as well as an inconvenience. Consider the following example:

#include <boost/asio.hpp>
 
int            main()
{
  boost::asio::io_service        io;
 
  boost::asio::ip::tcp::socket   s(io_service);
  return (0);
}

As you can see, this is getting a little too verbose and can lead to confusion. You could use "using", but you will loose all verbosity.

This is where aliases come in handy:

#include  <boost/asio.hpp>
 
namespace boost_tcp = boost::asio::ip::tcp;
 
int       main
{
  boost::asio::io_service        io;
 
  boost_tcp::socket   s(io_service);
  return (0);    
}

By making a alias, you can clear out your code while still keeping some verbosity.

[edit] Conclusion

Namespaces are not essential in order to make a functioning program, but it is a good practice and should be considered when writing at least a meduim-sized program, especially if it contains modules or APIs.