Upcoming Events
Unite 2010
11/10 - 11/12 @ Montréal, Canada

GDC China
12/5 - 12/7 @ Shanghai, China

Asia Game Show 2010
12/24 - 12/27  

GDC 2011
2/28 - 3/4 @ San Francisco, CA

More events...
Quick Stats
118 people currently visiting GDNet.
2406 articles in the reference section.

Help us fight cancer!
Join SETI Team GDNet!
Link to us Events 4 Gamers
Intel sponsors gamedev.net search:

The C++ Standard Library Part 1
Language Features


Namespaces

One trend in programming, and especially game programming, is the increased use of libraries from different sources. For example, a game might use a 3D rendering engine from Company A, a physics engine from Company B, a sound effects library from Company C and a networking library from Company D. On one hand, this is a good thing as it increased productivity; the game programmers can focus on making a game rather than implementing yet another 3D engine. On the other hand, the game programmer now needs to make sure that these different components work well together. One problem in getting components from different sources to work together is name collision.

Name collision happens when there are two or more functions with the same name, or even two or more classes with the same name. This usually manifests as duplicate symbol linking errors. To continue the game example, the 3D rendering engine may have a function process_BSP() and the 3D audio library might also have a function called process_BSP().

To address this problem, C++ has namespaces. Namespaces are used to group identifiers together in named logical bundles. In the game example, the developer might try to put all the video functions in a video namespace and all the audio functions in an audio namespace. In this way, the function names will no longer collide.

Putting things in a namespace is a lot like putting things into a class. For example, my personal code library lives in namespace aoi, so declaring things in that namespace can look like:

namespace aoi {
  class MyClass {
    // stuff
  };
  void my_function(void);
}

Of course the syntax of namespaces and classes aren't exactly the same. The namespace syntax is different from a class in that it doesn't need a semi-colon at the end of the closing brace (though putting one there doesn't hurt), and you can define the elements of a namespace over different files.

// header one:
namespace aoi {
  class MyFirstClass {
  };
}
 
// header two:
namespace aoi {
  class MySecondClass {
  };
}

To access elements inside a namespace you use the :: operator much like you would use to get at static members in a class.

aoi::MyClass my_object;
aoi::my_function();

Things inside the aoi namespace don't need to use the aoi:: prefix.

namespace aoi {
  class MyClass {
    public:
      MyClass();
      // stuff
  };
  void my_function(void);
 
  MyClass::MyClass() {
    my_function();
  }
}

Also when writing code outside of the namespace, you don't need to use the :: operator on functions if the functions takes an argument defined in the same namespace. [3]

namespace aoi {
  class MyClass {
    // stuff
  };
  void another_function(const MyClass &);
}
// outside the namespace
void some_other_function(void) {
  aoi::MyClass my_object;
  another_function(my_object); // doesn't need the aoi:: in front of another_function
}

This is usually transparent on the end of the person using the types in the namespace. However, this is a good reason to put non-member functions that work on a type in the same namespace as the type, especially overloaded operators.

namespace aoi {
  namespace string {
    class sortable_string {
      // stuff
    };
    bool operator<(const sortable_string & lhs, const sortable_string & rhs); // good
  }
  bool operator>(const string::sortable_string & lhs, const string::sortable_string & rhs); // bad
}

using

Another way to access identifiers in a namespace is by a using declaration or a using directive. With a using declaration, you can specify an identifier in a namespace to be treated as part of the current scope. For example:

namespace aoi {
  class MyClass {
    // stuff
  };
}
// outside the namespace
void some_other_function(void) {
  using aoi::MyClass; // You can use MyClass without the aoi:: for the rest of the function
 
  MyClass my_object;
}
 
MyClass global_object; // error: MyClass lives in namespace aoi and the using declaration was only
                       //   for the function's scope.

A using directive is a lot like a using declaration, but it pulls everything from a given namespace into a scope.

namespace aoi {
  class MyClass {
    // stuff
  };
  void my_function(void);
}
 
using namespace aoi; // using directive brings everything from aoi into the current scope
                     //   which is the global scope in this case
 
void some_other_function(void) {
  MyClass my_object; // neither of these need to use aoi:: to access the identifiers because
  my_function();     //   they are in a scope that has a using namespace aoi directive
}

You can also use a using declaration in the global scope or a using directive in a function scope. What you can't do is put either in a class scope, as the using keyword means something different inside a class definition. [4] You also can't declare a namespace inside a class.

struct SomeStruct {
  using aoi::MyClass;  // illegal
  using namespace aoi; // also illegal
  namespace aoi {      // this one too
  }
 
  void some_function(void) {
    using aoi::MyClass; // perfectly legal, lasts for the rest of the function
  }
};

One thing that is legal, but you shouldn't do, is put a using directive in a header file, as it can introduce subtle and hard to track down errors related to name lookups.

Also, when you don't explicitly put things inside a namespace, the identifier goes inside the global namespace, which you can access with operator:: with nothing before the ::.

void some_function(void); // this declares a function in the global namespace
namespace aoi {
  void some_function(void); // this declares a different function with the same name in
                            //   namespace aoi.
 
  void some_other_function(void) {
    some_function();      // calls aoi::some_function()
    aoi::some_function(); // also calls aoi::some_funciton()
    ::some_function();    // calls the first some_function() in the global namespace
  }
}

Also, even though you can't put a namespace in a class definition, you can put a namespace inside another namespace.

namespace aoi {
  namespace memory {
    class SegmentManager;
  }
}
 
aoi::memory::SegmentManager   sm1; // memory is nested inside aoi
::aoi::memory::SegmentManager sm2; // and aoi is nested inside the global namespace
 
using namespace aoi;
memory::SegmentManager sm3;   // still need the memory:: prefix
using memory::SegmentManager; // since there's a using namespace aoi, don't need to
                              //   prefix aoi:: here 
SegmentManager sm4;           // all good

However, using directives or declarations can introduce ambiguity.

namespace aoi {
  void foo(void);
}
namespace jun {
  void foo(void);
}
using aoi::foo;
using jun::foo;
void bar(void) {
  foo(); // error, doesn't know if this should be aoi::foo() or jun::foo()
}

This, however, becomes reasonable with one small change:

namespace aoi {
  void foo(void);
}
namespace jun {
  void foo(int);
}
using aoi::foo;
using jun::foo;
void bar(void) {
  foo();  // void aoi::foo(void);
  foo(1); // void jun::foo(int);
}

Here, because the two functions have different signatures, the compiler can resolve the ambiguity, much in the same way it can resolve the ambiguity from normal operator overloading. All the same, to prevent some subtle (and some not so subtle) errors, it's best to restrict using directives and declarations to the smallest needed scope.

Finally, preprocessor definitions don't respect namespace scoping (or any other scoping). Because macros work via text substitution before the code ever reaches the compiler, a macro defined inside one namespace will still affect code outside that namespace with or without a using directive.

namespace aoi {
  #define SILLY fred
}
 
int SILLY = 0; // creates a variable named fred, not SILLY

This also means using declarations for macro names will probably not do what you expect, if it compiles at all.

Namespaces and the Standard Library

So why are namespaces important for using the standard library? Most components of the standard library live in the namespace std. The classic "Hello World" program often looks like this:

#include <iostream>
 
int main(int, char **) {
  std::cout << "Hello World!" << std::endl;
 
  return 0;
}

Here cout and endl are parts of the standard library that live in namespace std. Of course, you can also use using directives and using declarations with namespace std.

#include <iostream>
using namespace std;
 
int main(int, char **) {
  cout << "Hello World!" << endl;
 
  return 0;
}
 
#include <iostream>
 
int main(int, char **) {
  using std::cout;
  using std::endl;
 
  cout << "Hello World!" << endl;
 
  return 0;
}

Though, for "Hello World", it's less typing just to put the std:: in front of cout and endl.

One other thing to note is that a using directive, like using namespace std, will only bring in the parts of the namespace that have already been declared in the headers included so far. For example, if you've only included <iostream> then using namespace std won't magically import the declarations from the <vector> header [5].

Also, the guideline not to put a using directive in a header file goes double for the std namespace. Because almost everything in the standard library is in namespace std, and because the standard library is so large, if you have using namespace std in a header, the opportunities for the aforementioned strange and subtle errors is nearly unbounded. In particular, some older compilers have a hard time dealing with a using directive followed by more entries in to the namespace.

// the moral equivalent of this may happen if you have a using directive in a header
#include <iostream>
using namespace std;
#include <vector>
 
vector<int> int_vector; // may not work properly

Other important namespaces include std::tr1 and boost. std::tr1 is the namespace where the components specified in Technical Report 1 have been placed in the few compilers that current support them. boost is the namespace used by the Boost C++ library which contains many implementations of components specified in Technical Report 1. At this point in time it is more portable to use the boost namespace, but hopefully in the future, std::tr1 will be more useful.





Templates


Contents
  Introduction
  Namespaces
  Templates
  Exceptions
  Closing and References

  Printable version
  Discuss this article

The Series
  Language Features
  std::vector