Chapter 8
Namespaces

Stefan Schirra (stschirr@mpi-sb.mpg.de)

Names, in particular (member) function names and class names should be descriptive and easily remembered. So it is not surprising that different libraries or packages choose the same name for corresponding or similar classes and functions. A common approach to solving the naming problem is to add a prefix, for example, OpenGL adds gl and FLTK adds fl. LEDA uses prefix leda_ to some extent, but you have to tell LEDA not to make the corresponding unprefixed names available as well.1 Initially, CGAL used prefix CGAL_. At the beginning of 1999, it was decided to drop prefix CGAL_ and to introduce namespace CGAL.

8.1   What are namespaces

A namespace is a scope with a name.2 Inside the namespace, i.e., the named scope, all names defined in that scope (and made known to the compiler) can be used directly. Outside a namespace, a name defined in the namespace has to be qualified3 by the namespace name, for example CGAL::Object, or they have to be made usable without qualification by a so-called using declaration,
using CGAL::Object;
Object obj;  // name is now known
There is also a statement to make all names from a namespace available in another scope, but this is a bad idea. Actually, in order not to set a bad example, we recommend not to use this in CGAL's example and demo programs.

8.2   Namespace std

The names form the standard C++ library, especially those from the standard template library, are (supposed to be) in namespace std. This subsumes the I/O-library and also the C-library functions. You have to qualify streams and so by std::, too. That is:
std::cout << "Hello CGAL" << std::endl;
or you have to add using declarations for the names you want to use without std:: qualification. Whenever a platform does not put names into namespace std, CGAL adds the names it needs to namespace std. This is done by the configuration tools.

As for the C-library functions, you should use the macro CGAL_CLIB_STD instead of std:

CGAL_CLIB_STD::isspace(c)

8.3   Namespace CGAL

All names introduced by CGAL should be in namespace CGAL, e.g.:
#include <something>

namespace CGAL {

class My_new_cgal_class {};

My_new_cgal_class 
my_new_function( My_new_cgal_class& );

} // namespace CGAL
Make sure not to have include statements nested between namespace CGAL { and } // namespace CGAL. Otherwise all names defined in the file included will be added to namespace CGAL. (Some people use the macros CGAL_BEGIN_NAMESPACE and CGAL_END_NAMESPACE in place of the namespace CGAL { and } // namespace CGAL, respectively, for better readability.)

8.4   Name lookup

The process of searching for a definition of a name detected in some scope is called name lookup. Simply speaking, name lookup looks up names in the scope where the name is used, and if not found, the lookup proceeds in successively enclosing scope until the name is found. It terminates as soon as the name is found, no matter whether the name found fits or not. If a name is qualified by a namespace name, that namespace is searched for the name.

8.4.1   Argument-dependent name lookup

Unqualified name lookup, i.e., lookup when there is no namespace or class name and no scope resolution operator ::, proceeds like qualified name lookup, but name lookup for a function call is supposed to search also the namespaces of the argument types for a matching function name. This is sometimes called Koenig-lookup.

8.4.2   Point of instantiation of a template

Name lookup in a template is slightly more complicated. Names that do not depend on template parameters are looked up at the point of definition of the template (so they must be known at the point of definition). Names depending on the template parameters are looked up at the point of instantiation of the template. The name is searched for in the scope of the point of instantiation and the scope of the point of definition. Here is a small example:

namespace A {

template <class T>
const T&
mix(const T& a1, const T& a2)
{ return a1 < a2 ? a1 : a2; } 

template <class T>
const T&
use(const T& a1, const T& a2)
{ return mix( a1, a2); }

} // namespace A

namespace B {

template <class T>
const T&
mix(const T& a1, const T& a2)
{ return a2 < a1 ? a1 : a2; } 

double
use_use( const double& t1, const double& t2)
{ return A::use(t1,t2); }

} // namespace B

int
main()
{
  B::use_use( 0.0, 1.0);
  return 0;
}

There is a ambiguity, because both the scope enclosing the point of instantiation and the scope enclosing the point of definition contain a mix function. The mips compiler on IRIX complains about this ambiguity:

bash-2.03$ CC -64 poi.cpp 
cc-1282 CC: ERROR File = poi.cpp, Line = 11
  More than one instance of overloaded function "mix" matches the argument list.

            Function symbol function template "B::mix(const T &, const T &)"
                      is ambiguous by inheritance.
            Function symbol function template "A::mix(const T &, const T &)"
                      is ambiguous by inheritance.
            The argument types are:  (const double, const double).
  { return mix( a1, a2); }
           ^
          detected during instantiation of
                    "const double &A::use(const double &, const double &)" 

1 error detected in the compilation of "poi.cpp".
There wouldn't be any problems, if B::use_use() would be a template function as well, because this would move the point of instantiation into global scope.

By the way, gcc 2.95 uses the function defined at the point of definition.

8.5   Namespace CGAL::NTS

Note: This section will be revised once the forthcoming revision of the C++-standard gets into a more definite state. The standard library has similar problems, e.g. for swap(), see issues 225, 226, and 229. Currently, CGAL::NTS does not exist anymore, and the CGAL_NTS macro boils down to CGAL::. As the future interface is not yet fixed, people should still follow the guidelines given below.

What are the conclusions from the previous subsection. If A plays the role of std and B the role of CGAL, we can conclude that CGAL should not define template functions that are already defined in namespace std, especially min and max. Also, letting CGAL be namespace A, we should not define templates in CGAL that are likely to conflict with templates in other namespaces (playing the role of B): Assume that both CGAL and some other namespace define an is_zero() template. Then an instantiation of some CGAL template using is_zero() that takes place inside the other namespace causes trouble. For this reason, we have another namespace NTS nested in CGAL, which contains potentially conflicting template functions.

8.5.1   Which function calls should be qualified in CGAL code?

Out current policy is: Summarizing, you can always qualify functions on number types with CGAL_NTS besides min and max.


Footnotes

 1  CGAL's makefile does this by setting -DLEDA_PREFIX.
 2  There are also unnamed namespaces. They are intented to replace file scope.
 3  This is a somewhat simplified view; read further for more details.
 4  The use of the macro eases future changes in our policy.