Chapter 4: Namespaces

4.1: Namespaces

Imagine a math teacher who wants to develop an interactive math program. For this program functions like cos, sin, tan etc. are to be used accepting arguments in degrees rather than arguments in radians. Unfortunately, the function name cos is already in use, and that function accepts radians as its arguments, rather than degrees.

Problems like these are usually solved by defining another name, e.g., the function name cosDegrees is defined. C++ offers an alternative solution through namespaces. Namespaces can be considered as areas or regions in the code in which identifiers may be defined. Identifiers defined in a namespace normally won't conflict with names already defined elsewhere (i.e., outside of their namespaces). So, a function cos (expecting angles in degrees) could be defined in a namespace Degrees. When calling cos from within Degrees you would call the cos function expecting degrees, rather than the standard cos function expecting radians.

4.1.1: Defining namespaces

Namespaces are defined according to the following syntax:
    namespace identifier
    {
        // declared or defined entities
        // (declarative region)
    }
The identifier used when defining a namespace is a standard C++ identifier.

Within the declarative region, introduced in the above code example, functions, variables, structs, classes and even (nested) namespaces can be defined or declared. Namespaces cannot be defined within a function body. However, it is possible to define a namespace using multiple namespace declarations. Namespaces are `open' meaning that a namespace CppAnnotations could be defined in a file file1.cc and also in a file file2.cc. Entities defined in the CppAnnotations namespace of files file1.cc and file2.cc are then united in one CppAnnotations namespace region. For example:

    // in file1.cc
    namespace CppAnnotations
    {
        double cos(double argInDegrees)
        {
            ...
        }
    }

    // in file2.cc
    namespace CppAnnotations
    {
        double sin(double argInDegrees)
        {
            ...
        }
    }
Both sin and cos are now defined in the same CppAnnotations namespace.

Namespace entities can be defined outside of their namespaces. This topic is discussed in section 4.1.4.1.

4.1.1.1: Declaring entities in namespaces

Instead of defining entities in a namespace, entities may also be declared in a namespace. This allows us to put all the declarations in a header file that can thereupon be included in sources using the entities defined in the namespace. Such a header file could contain, e.g.,
    namespace CppAnnotations
    {
        double cos(double degrees);
        double sin(double degrees);
    }

4.1.1.2: A closed namespace

Namespaces can be defined without a name. Such an anonymous namespace restricts the visibility of the defined entities to the source file defining the anonymous namespace.

Entities defined in the anonymous namespace are comparable to C's static functions and variables. In C++ the static keyword can still be used, but its preferred use is in class definitions (see chapter 7). In situations where in C static variables or functions would have been used the anonymous namespace should be used in C++.

The anonymous namespace is a closed namespace: it is not possible to add entities to the same anonymous namespace using different source files.

4.1.2: Referring to entities

Given a namespace and its entities, the scope resolution operator can be used to refer to its entities. For example, the function cos() defined in the CppAnnotations namespace may be used as follows:
    // assume CppAnnotations namespace is declared in the
    // following header file:
    #include <cppannotations>

    int main()
    {
        cout << "The cosine of 60 degrees is: " <<
                CppAnnotations::cos(60) << '\n';
    }
This is a rather cumbersome way to refer to the cos() function in the CppAnnotations namespace, especially so if the function is frequently used. In cases like these an abbreviated form can be used after specifying a using declaration. Following
    using CppAnnotations::cos;  // note: no function prototype,
                                // just the name of the entity
                                // is required.
calling cos results in a call of the cos function defined in the CppAnnotations namespace. This implies that the standard cos function, accepting radians, is not automatically called anymore. To call that latter cos function the plain scope resolution operator should be used:
    int main()
    {
        using CppAnnotations::cos;
        ...
        cout << cos(60)         // calls CppAnnotations::cos()
            << ::cos(1.5)       // call the standard cos() function
            << '\n';
    }
A using declaration can have restricted scope. It can be used inside a block. The using declaration prevents the definition of entities having the same name as the one used in the using declaration. It is not possible to specify a using declaration for a variable value in some namespace, and to define (or declare) an identically named object in a block also containing a using declaration. Example:
    int main()
    {
        using CppAnnotations::value;
        ...
        cout << value << '\n';  // uses CppAnnotations::value
        int value;              // error: value already declared.
    }

4.1.2.1: The `using' directive

A generalized alternative to the using declaration is the using directive:
    using namespace CppAnnotations;
Following this directive, all entities defined in the CppAnnotations namespace are used as if they were declared by using declarations.

While the using directive is a quick way to import all the names of a namespace (assuming the namespace has previously been declared or defined), it is at the same time a somewhat dirty way to do so, as it is less clear what entity is actually used in a particular block of code.

If, e.g., cos is defined in the CppAnnotations namespace, CppAnnotations::cos is going to be used when cos is called. However, if cos is not defined in the CppAnnotations namespace, the standard cos function will be used. The using directive does not document as clearly as the using declaration what entity will actually be used. Therefore use caution when applying the using directive.

Namespace declarations are context sensitive: when a using namespace declaration is specified inside a compound statement then the declaration is valid until the compound statement's closing curly bracket has been encountered. In the next example a string first is defined without explicit specifying std::string, but once the compound statement has ended the scope of the using namespace std declaration has also ended, and so std:: is required once again when defining second:

    #include <string>
    int main()
    {
        {
            using namespace std;
            string first;
        }
        std::string second;
    }
A using namespace directive cannot be used within the declaration block of a class- or enumeration-type. E.g., the following example won't compile:
    struct Namespace
    {
        using namespace std;      // won't compile
    };

4.1.2.2: `Koenig lookup'

If Koenig lookup were called the `Koenig principle', it could have been the title of a new Ludlum novel. However, it is not. Instead it refers to a C++ technicality.

`Koenig lookup' refers to the fact that if a function is called without specifying its namespace, then the namespaces of its argument types are used to determine the function's namespace. If the namespace in which the argument types are defined contains such a function, then that function is used. This procedure is called the `Koenig lookup'.

As an illustration consider the next example. The function FBB::fun(FBB::Value v) is defined in the FBB namespace. It can be called without explicitly mentioning its namespace:

    #include <iostream>

    namespace FBB
    {
        enum Value        // defines FBB::Value
        {
            FIRST
        };

        void fun(Value x)
        {
            std::cout << "fun called for " << x << '\n';
        }
    }

    int main()
    {
        fun(FBB::FIRST);    // Koenig lookup: no namespace
                            // for fun() specified
    }
    /*
        generated output:
    fun called for 0
    */
The compiler is rather smart when handling namespaces. If Value in the namespace FBB would have been defined as typedef int Value then FBB::Value would be recognized as int, thus causing the Koenig lookup to fail.

As another example, consider the next program. Here two namespaces are involved, each defining their own fun function. There is no ambiguity, since the argument defines the namespace and FBB::fun is called:

    #include <iostream>

    namespace FBB
    {
        enum Value        // defines FBB::Value
        {
            FIRST
        };

        void fun(Value x)
        {
            std::cout << "FBB::fun() called for " << x << '\n';
        }
    }

    namespace ES
    {
        void fun(FBB::Value x)
        {
            std::cout << "ES::fun() called for " << x << '\n';
        }
    }

    int main()
    {
        fun(FBB::FIRST);    // No ambiguity: argument determines
                            // the namespace
    }
    /*
        generated output:
    FBB::fun() called for 0
    */

Here is an example in which there is an ambiguity: fun has two arguments, one from each namespace. The ambiguity must be resolved by the programmer:

    #include <iostream>

    namespace ES
    {
        enum Value        // defines ES::Value
        {
            FIRST
        };
    }

    namespace FBB
    {
        enum Value        // defines FBB::Value
        {
            FIRST
        };

        void fun(Value x, ES::Value y)
        {
            std::cout << "FBB::fun() called\n";
        }
    }

    namespace ES
    {
        void fun(FBB::Value x, Value y)
        {
            std::cout << "ES::fun() called\n";
        }
    }

    int main()
    {
        //  fun(FBB::FIRST, ES::FIRST); ambiguity: resolved by
        //                              explicitly mentioning
        //                              the namespace
        ES::fun(FBB::FIRST, ES::FIRST);
    }
    /*
        generated output:
    ES::fun() called
    */

An interesting subtlety with namespaces is that definitions in one namespace may break the code defined in another namespace. It shows that namespaces may affect each other and that namespaces may backfire if we're not aware of their peculiarities. Consider the following example:

    namespace FBB
    {
        struct Value
        {};

        void fun(int x);
        void gun(Value x);
    }

    namespace ES
    {
        void fun(int x)
        {
            fun(x);
        }
        void gun(FBB::Value x)
        {
            gun(x);
        }
    }
Whatever happens, the programmer'd better not use any of the ES::fun functions since it results in infinite recursion. However, that's not the point. The point is that the programmer won't even be given the opportunity to call ES::fun since the compilation fails.

Compilation fails for gun but not for fun. But why is that so? Why is ES::fun flawlessly compiling while ES::gun isn't? In ES::fun fun(x) is called. As x's type is not defined in a namespace the Koenig lookup does not apply and fun calls itself with infinite recursion.

With ES::gun the argument is defined in the FBB namespace. Consequently, the FBB::gun function is a possible candidate to be called. But ES::gun itself also is possible as ES::gun's prototype perfectly matches the call gun(x).

Now consider the situation where FBB::gun has not yet been declared. Then there is of course no ambiguity. The programmer responsible for the ES namespace is resting happily. Some time after that the programmer who's maintaining the FBB namespace decides it may be nice to add a function gun(Value x) to the FBB namespace. Now suddenly the code in the namespace ES breaks because of an addition in a completely other namespace (FBB). Namespaces clearly are not completely independent of each other and we should be aware of subtleties like the above. Later in the C++ Annotations (chapter 11) we'll return to this issue.

4.1.3: The standard namespace

The std namespace is reserved by C++. The standard defines many entities that are part of the runtime available software (e.g., cout, cin, cerr); the templates defined in the Standard Template Library (cf. chapter 18); and the Generic Algorithms (cf. chapter 19) are defined in the std namespace.

Regarding the discussion in the previous section, using declarations may be used when referring to entities in the std namespace. For example, to use the std::cout stream, the code may declare this object as follows:

    #include <iostream>
    using std::cout;
Often, however, the identifiers defined in the std namespace can all be accepted without much thought. Because of that, one frequently encounters a using directive, allowing the programmer to omit a namespace prefix when referring to any of the entities defined in the namespace specified with the using directive. Instead of specifying using declarations the following using directive is frequently encountered: construction like
    #include <iostream>
    using namespace std;
Should a using directive, rather than using declarations be used? As a rule of thumb one might decide to stick to using declarations, up to the point where the list becomes impractically long, at which point a using directive could be considered.

Two restrictions apply to using directives and declarations:

4.1.4: Nesting namespaces and namespace aliasing

Namespaces can be nested. Here is an example:
    namespace CppAnnotations
    {
        int value;
        namespace Virtual
        {
            void *pointer;
        }
    }
The variable value is defined in the CppAnnotations namespace. Within the CppAnnotations namespace another namespace (Virtual) is nested. Within that latter namespace the variable pointer is defined. To refer to these variable the following options are available:

Following a using namespace directive all entities of that namespace can be used without any further prefix. If a single using namespace directive is used to refer to a nested namespace, then all entities of that nested namespace can be used without any further prefix. However, the entities defined in the more shallow namespace(s) still need the shallow namespace's name(s). Only after providing specific using namespace directives or using declarations namespace qualifications can be omitted.

When fully qualified names are preferred but a long name like

    CppAnnotations::Virtual::pointer
is considered too long, a namespace alias may be used:
    namespace CV = CppAnnotations::Virtual;
This defines CV as an alias for the full name. The variable pointer may now be accessed using:
    CV::pointer = 0;
A namespace alias can also be used in a using namespace directive or using declaration:
    namespace CV = CppAnnotations::Virtual;
    using namespace CV;

Nested namespace definitions (C++17)

Starting with the C++17 standard, when nesting namespaces a nested namespace can directly be referred to using scope resolution operators. E.g.,

    namespace Outer::Middle::Inner
    { 
        // entities defined/declared here are defined/declared in the Inner
        // namespace, which is defined in the Middle namespace, which is
        // defined in the Outer namespace
    }

4.1.4.1: Defining entities outside of their namespaces

It is not strictly necessary to define members of namespaces inside a namespace region. But before an entity is defined outside of a namespace it must have been declared inside its namespace.

To define an entity outside of its namespace its name must be fully qualified by prefixing the member by its namespaces. The definition may be provided at the global level or at intermediate levels in the case of nested namespaces. This allows us to define an entity belonging to namespace A::B within the region of namespace A.

Assume the type int INT8[8] is defined in the CppAnnotations::Virtual namespace. Furthermore assume that it is our intent to define a function squares, inside the namespace
CppAnnotations::Virtual returning a pointer to CppAnnotations::Virtual::INT8.

Having defined the prerequisites within the CppAnnotations::Virtual namespace, our function could be defined as follows (cf. chapter 9 for coverage of the memory allocation operator new[]):

    namespace CppAnnotations
    {
        namespace Virtual
        {
            void *pointer;

            typedef int INT8[8];

            INT8 *squares()
            {
                INT8 *ip = new INT8[1];

                for (size_t idx = 0; idx != sizeof(INT8) / sizeof(int); ++idx)
                    (*ip)[idx] = (idx + 1) * (idx + 1);

                return ip;
            }
        }
    }
The function squares defines an array of one INT8 vector, and returns its address after initializing the vector by the squares of the first eight natural numbers.

Now the function squares can be defined outside of the CppAnnotations::Virtual namespace:

    namespace CppAnnotations
    {
        namespace Virtual
        {
            void *pointer;

            typedef int INT8[8];

            INT8 *squares();
        }
    }

    CppAnnotations::Virtual::INT8 *CppAnnotations::Virtual::squares()
    {
        INT8 *ip = new INT8[1];

        for (size_t idx = 0; idx != sizeof(INT8) / sizeof(int); ++idx)
            (*ip)[idx] = (idx + 1) * (idx + 1);

        return ip;
    }
In the above code fragment note the following:

Finally, note that the function could also have been defined in the CppAnnotations region. In that case the Virtual namespace would have been required when defining squares() and when specifying its return type, while the internals of the function would remain the same:

    namespace CppAnnotations
    {
        namespace Virtual
        {
            void *pointer;

            typedef int INT8[8];

            INT8 *squares();
        }

        Virtual::INT8 *Virtual::squares()
        {
            INT8 *ip = new INT8[1];

            for (size_t idx = 0; idx != sizeof(INT8) / sizeof(int); ++idx)
                (*ip)[idx] = (idx + 1) * (idx + 1);

            return ip;
        }
    }