On C++ Namespaces

Introduction

Since it’s creation by Bjarne Stroustrup, C++ has undergone
extensive changes, specially in more recent years by the C++ Standards
Committee. Several new features have been added to the basic language,
including templates, exception handling, run time type information, and, of
course, namespaces.

You might be inclined to believe that namespaces don’t affect you
one way or another unless you decide to use them, but they do. The C++
Standards Committee has basically rewritten the Standard Library, placing most
of its facilities inside a namespace called std. This change alone
forces changes in existing pre-draft programs that use the SL.

But, What’s a namespace, really?

A namespace defines a new scope. Members of a namespace are said
to have namespace scope. They provide a way to avoid name collisions (of
variables, types, classes or functions) without some of the restrictions
imposed by the use of classes, and without the inconvenience of handling nested
classes.

Defining a namespace is similar to defining a class. First goes
the namespace keyword, followed by the identifier (the namespace
name), followed by member declarations enclosed in braces. For example:

namespace direct {
  class Arrow
  {
  public:
    Arrow(int dir);
    void  setDirection(int dir);
  private:
    int   direction;
  }
  // ...... other stuff
}

A namespace, however, cannot have access specifiers, such as public:
or private:. All members of a namespace are public. It cannot have
a trailing semicolon, either. An important difference between classes and
namespaces, is that class definitions are said to be closed, meaning that, once
defined, new members cannot be added to it. A namespace definition is open, and
can be split over several units. For example:

// file SY.h
namespace SY {
  class Maker { ... };
  class SuperMaker : public Maker { ... };
}

// file  data.h
namespace SY {
  class Binder { ... };
  class DataBinder : public Binder { ... };
}

In this example, there are two files (SY.h
and data.h), both defining namespace SY. The definition of SY on data.h does
not conflict with the one in
SY.h, but actually extends it. If you look
closely at the Standard Library, you’ll notice that no single header file
declares all members of namespace std. Each file only declares
some members, adding them to the global std namespace.

Using Namespaces

There are four ways you can refer to namespace members:

  • Using the full member name, including the namespace it belongs to. For example: 
      std::cout << "Hello Nasty";
    	

    Note: Remember that on Pre-Draft days, cout was not declared in any namespace
    (they didn’t exist yet, anyway), and header files used an .h suffix.

  • By taking advantage of Using-Declarations, as in 
      using std::cout;
      cout << "Hello Nasty";
    	

    this declares cout in the current scope as synonym for std::cout.

  • By taking advantage of Using-Directives, as in 
      using namespace std;
      cout << "Hello Nasty";
    	

    which specifies that the current scope can refer to names in the std
    namespace without using full qualifiers. This is mostly used when porting
    legacy code.

  • Using aliases. Say, for example, I have 
      namespace X
      {
        namespace Y
        {
          class Z { ... };
        }
      }
    	

    The full qualifier for Z is X::Y::Z, but we can declare an alias
    using

      namespace w = X::Y;
    	

    This declares w as an alias for namespace X::Y, thus we can access Z using w::Z.

    Note: As you can see, namespaces can be nested. One of the design goals of
    namespaces was to encourage programmers and vendors to wrap their libraries
    inside them, minimizing name collisions. One particularly useful way of taking
    advantage of this is when you are designing libraries for, say, your company,
    which involve several pieces of functionality. For example, I keep some of my
    reusable system classes and templates in a WRuntime namespace,
    which contains different namespaces inside it like WThreading and
    WLogging
    .

Unnamed Namespaces

Until now, I’ve only covered named namespaces, but you can
also declare unnamed namespaces. Take for example:

  namespace
  {
    class Car
    {
      .... // class members here
    }
    // other members here
  }

this definition behaves exactly like:

  namespace __UniqueName__
  {
    class Car
    {
      .... // class members here
    }
    // other members here
  }

  using namespace __UniqueName__;

For each unnamed namespace, the compiler generates a unique name
(represented here by __UniqueName__), which differs from every other
name in the program. You might be asking yourself, What’s the use of this?

Let’s see the example above. Class Car is defined in an unnamed
namespace declared at global scope, thus, it can be referred to as if it were
declared directly at global scope. However, since it’s a member of an unnamed
namespace, the compiler mangles its name with the generated namespace name, so
it won’t conflict with other names.

Unnamed namespaces can also be defined inside other namespaces.
Suppose the unnamed namespace in the example above was declared inside
namespace foo. Then class Car could be referred to as foo::Car.
Notice there’s no mention of the unnamed namespace, but the link name for Car
will still be mangled with namespace foo and the unique name generated for the
unnamed namespace by the compiler.

An interesting use of unnamed namespaces is hiding names inside
modules. Before, this would be done using the static keyword, but
the new C++ Standard reads in section 7.3.1.1 Unnamed Spaces, paragraph 2:

“The use of the static keyword is deprecated when declaring objects in a
namespace scope, the unnamed namespace provides a superior alternative.” 

In case you’ve forgotten (or didn’t know), static, when applied at
namespace scope, specifies internal linkage. However, static only
applies to names of objects, functions and anonymous unions, not to type
declarations.

Personally, I feel that, while unnamed namespaces are a far better solution
than static to this problem, it’s not the best that could have been
implemented. To me, using unnamed namespaces in this way seem to be too much
like taking advantage of a “side” effect of the lack of name of the namespace.
I would feel much more comfortable with an appropriately named keyword to
accomplish this behavior (think hidden or internal),
but then again, I’m no language lawyer, nor am I completely informed of the
reasons why the committee chose it that way.

Conclusion

Namespaces are a powerful addition to an already powerful
language, giving the programmer more flexibility, provided he knows how to take
advantage of it. Please consider the use of namespaces carefully when planning
your next project, you might be surprised at how useful they can be.

3 comments

  1. Great post! This was really helpful. Thanks. I also agree that there should be keyword for the unamed namespaces instead of leaving them blank. It’s better to be verbose in programming.

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>