Namespaces

"The road to hell is paved with global variables" -- Steve McConnell

Namespaces

A simple program with 3 global symbols:
#include <iostream>
using namespace std;

int foo = 1;        // in global namespace
int bar = 2;        // in global namespace

int Div2(int value) // in global namespace
{
  return value / 2;
}

int main(void)
{
  cout << foo << endl;     // use global foo
  cout << bar << endl;     // use global bar
  cout << Div2(8) << endl; // use global Div2
  return 0;
}
Placing these symbols in a namespace will prevent the program from compiling:
int main(void)
{
  cout << foo << endl;     //error, foo is undeclared
  cout << bar << endl;     // error, bar is undeclared
  cout << Div2(8) << endl; // error, Div2 is undeclared
  return 0;
}
We need to qualify the symbols in the namespace:
int main(void)
{
  cout << AdvancedCppProgramming::foo << endl;     
  cout << AdvancedCppProgramming::bar << endl;     
  cout << AdvancedCppProgramming::Div2(8) << endl; 
  return 0;
}
The general form of a namespace definition is:
namespace user-defined-name
{
  declaration/definition
  declaration/definition
  ...
}

Multiple Definitions in Scope

Consider this code:
#include <iostream>
using namespace std;

int foo = 11;  // in global namespace scope
int bar = 12;  // in global namespace scope

namespace AdvancedCppProgramming 
{
  int foo = 1;    
  int bar = 2;    
  int f1(int x) { return x / 2; }
}

namespace AdvancedCppProgramming 
{
  int f2(void) { return foo * 33; }    // AdvancedCppProgramming::foo
  int f3(void) { return ::foo * 33; }  // global foo
}

int f1(int x) // in global namespace scope
{
  return x / 4;
}

int main(void)
{
  int foo = 21; // local scope
  int bar = 22; // local scope

  cout << foo << endl;                           // from local scope
  cout << AdvancedCppProgramming::foo << endl;   // from ACP namespace scope
  cout << ::foo << endl;                         // from global namespace scope

  cout << AdvancedCppProgramming::f1(8) << endl; // from ACP namespace scope
  cout << f1(8) << endl;                         // from global namespace scope
  cout << ::f1(8) << endl;                       // from global namespace scope

  return 0;
}

Hiding and Ambiguity

#include <iostream>
#include <cmath>

int main(void)
{
  std::cout << sqrt(25.0) << std::endl;   // calls sqrt in cmath
  std::cout << ::sqrt(25.0) << std::endl; // calls sqrt in cmath
  return 0;
}
In the above, compilers from GNU (g++ 3.3), Microsoft (6.0 and 7.1), and Borland (5.5.1) compile and produce the expected results. However, using version 5.6.4 from Borland yields this compiler error:
Error E2268 main.cpp 19: Call to undefined function 'sqrt' in function main()
Error E2268 main.cpp 20: Call to undefined function 'sqrt' in function main()
Adding a using namespace directive:
#include <iostream>
#include <cmath>
using namespace std;
solves the "problem" with Borland's compiler. However, using the explicit namespace:
std::cout << std::sqrt(25.0) << std::endl;   // calls sqrt in cmath
causes MS 6.0 to fail:
main.cpp(22) : error C2039: 'sqrt' : is not a member of 'std'


Now what happens?

#include <iostream>
#include <cmath>

double sqrt(double x)
{
  return x;
}

int main(void)
{
  std::cout << sqrt(25.0) << std::endl;   // Which one?
  std::cout << ::sqrt(25.0) << std::endl; // Which one?
  return 0;
}
The new sqrt function hides the one from cmath and prevents us from using it now. Note that Microsoft 6.0, g++ 3.3, and Borland 5.6.4 handle this correctly, but MS 7.1 and Borland's 5.5 compiler issue an error. Borland says for both lines:
Ambiguity between 'std::sqrt(double)' and 'sqrt(double)' in function main()
And MS 7.1 says:
main.cpp(41) : error C2169: 'sqrt' : intrinsic function, cannot be defined
which can be fixed with:
#pragma function(sqrt)


To "unhide" the function, we can "wrap" our new global:

#include <iostream>
#include <cmath>

namespace MyMathFunctions
{
  double sqrt(double x)
  {
    return x;
  }
}

int main(void)
{
  std::cout << MyMathFunctions::sqrt(25.0) << std::endl;  // calls MyMathFunctions::sqrt in this file
  std::cout << sqrt(25.0) << std::endl;                   // calls sqrt in cmath
  std::cout << ::sqrt(25.0) << std::endl;                 // calls sqrt in cmath
  return 0;
}
The only compiler that had a "problem" with the above code was Borland's 5.6.4 compiler:
Error E2268 main.cpp 73: Call to undefined function 'sqrt' in function main()
Error E2268 main.cpp 74: Call to undefined function 'sqrt' in function main()
which, again, is what you would expect.


A more disturbing example:

#include <iostream>
#include <cmath>

double sqrt(double x) { return x; };

int main(void)
{
  std::cout << ::sqrt(25.0) << std::endl;    // Global sqrt function defined in this file
  std::cout << sqrt(25.0) << std::endl;      // Global sqrt function defined in this file
  std::cout << std::sqrt(25.0) << std::endl; // sqrt from cmath
  return 0;
}
The output should be (as produced by Borland's 5.6.4 compiler):
25 
25
5
However, MS 6.0 gives this error for the third line:
error C2039: 'sqrt' : is not a member of 'std'
and GNU 3.3 and MS 7.1 both compile without errors but print this:
25
25
25

A final attempt:

#include <iostream>
#include <cmath>
using namespace std;

double sqrt(double x) 
{ 
  return x; 
};

int main(void)
{
  cout << sqrt(25.0) << endl;      // sqrt function defined in this file
  cout << ::sqrt(25.0) << endl;    // sqrt function defined in this file
  cout << std::sqrt(25.0) << endl; // sqrt function defined in cmath
  return 0;
}
Results:
Borland 5.6.4 (1): Ambiguity between 'std::sqrt(double)' and 'sqrt(double)' in function main()
Borland 5.5 (1,2): Ambiguity between 'std::sqrt(double)' and 'sqrt(double)' in function main()
MS 6.0 (3): 'sqrt' : is not a member of 'std'
GNU, MS 7.1:  Compiles cleanly, calls sqrt in file for all.

The moral of the story is that you must be aware of the compliancy of your compiler, libraries, and the specifications of the C++ Standard.

Same examples using math.h


Unnamed Namespaces

What happens when we run out of unique names for namespaces?
#include <iostream>

namespace
{
  double sqrt(double x) { return x; };
}

int main(void)
{
  std::cout << sqrt(25.0) << std::endl;   // No qualification needed
  return 0;
}
Now, this call should fail within main, but all compilers but MS C++ 6.0 succeed:
int main(void)
{
  std::cout << ::sqrt(25.0) << std::endl;   // Calling sqrt() function in global namespace scope
  return 0;
}
There isn't any sqrt() in the global namespace scope. With MSVC++ 6.0, this produces this error message:
error C2039: 'sqrt' : is not a member of '`global namespace''


If we have a symbol in an unnamed namespace that is the same as a global symbol in our program, we won't be able to access the symbol in the unnamed namespace. The example below is similar to the one above:

#include <iostream>
#include <cmath>
using namespace std;

namespace
{
  double sqrt(double x) { return x; };
}

double sqrt(double x) { return x; };

int main(void)
{
  cout << ::sqrt(25.0) << endl;      // Global sqrt function defined in this file
  cout << sqrt(25.0) << endl;        // Ambiguous (from global or unnamed namespace?)
  cout << std::sqrt(25.0) << endl;   // OK, from std namespace
  return 0;
}

Class Design Tip: When hiding symbols at the file scope, prefer to use unnamed namespaces over the already-overloaded-too-much C static keyword. Refresh your knowledge of the use of static.


Nested Namespaces

#include <iostream>
using namespace std;

namespace DigiPenInstituteOfTechnology
{
  int Div2(int x) {return x / 2;}
  
  namespace IntroductoryProgramming
  {
    int Div2(int x) {return x / 2;}
  }

  namespace AdvancedProgramming
  {
    int Div2(int x) {return x >> 1;}
  }
}

int main(void)
{
  cout << DigiPenInstituteOfTechnology::Div2(8) << endl;
  cout << DigiPenInstituteOfTechnology::IntroductoryProgramming::Div2(8) << endl;
  cout << DigiPenInstituteOfTechnology::AdvancedProgramming::Div2(8) << endl;

  return 0;
}

Namespace Aliases

Given these namespaces:
namespace AdvancedProgramming 
{
  int foo = 11;    
  int bar = 12;    
  int f1(int x)  { return x / 2; }
}

namespace DigiPenInstituteOfTechnology
{
  namespace IntroductoryProgramming
  {
    int foo = 21;    
    int bar = 22;    
    int Div2(int x) {return x / 2; }
  }

  namespace AdvancedProgramming
  {
    int foo = 31;    
    int bar = 32;    
    int Div2(int x) {return x >> 1; }
  }
}
using them requires a lot of typing:
int main(void)
{
  cout << AdvancedProgramming::foo << endl;
  cout << DigiPenInstituteOfTechnology::AdvancedProgramming::foo << endl;
  
  cout << DigiPenInstituteOfTechnology::IntroductoryProgramming::Div2(8) << endl;
  cout << DigiPenInstituteOfTechnology::AdvancedProgramming::Div2(8) << endl;

  return 0;
}
To allow unique namespaces and to shorten the names, you can create a namespace alias
  // Declare these after the namespace definitions above
namespace AP = AdvancedProgramming;
namespace DIT = DigiPenInstituteOfTechnology;

int main(void)
{
  // Now, use the shorter aliases
  cout << AP::foo << endl;
  cout << DIT::AdvancedProgramming::foo << endl;
  
  cout << DIT::IntroductoryProgramming::Div2(8) << endl;
  cout << DIT::AdvancedProgramming::Div2(8) << endl;

  return 0;
}
Creating aliases for nested namespaces as well:
namespace DIT_IP = DigiPenInstituteOfTechnology::IntroductoryProgramming;
namespace DIT_AP = DIT::AdvancedProgramming;  // uses previous alias

  // multiple aliases
namespace CS120 = DIT::IntroductoryProgramming;
namespace CS220 = DIT::AdvancedProgramming;

int main(void)
{
    // AdvancedProgramming::foo
  cout << AP::foo << endl;             

    // DigiPenInstituteOfTechnology::AdvancedProgramming::foo;
  cout << DIT_AP::foo << endl;         
  
    // DigiPenInstituteOfTechnology::IntroductoryProgramming::Div2;
  cout << DIT_IP::Div2(8) << endl;
  cout << CS120::Div2(8) << endl;

    // DigiPenInstituteOfTechnology::AdvancedProgramming::Div2;
  cout << DIT_AP::Div2(8) << endl;
  cout << CS220::Div2(8) << endl;

  return 0;
}
Note that you can't do this:
    // DigiPenInstituteOfTechnology::AdvancedProgramming::foo??
  cout << DIT::AP::foo << endl;             
because AP is not a member of the DIT namespace. (It's not a substitution like the preprocessor performs with a #define.)

Class Design Tip: Don't create very terse namespaces (like std). Create unique and meaningful namespaces and allow the user to create shorthand notation with aliases.


Using Declarations

using DigiPenInstituteOfTechnology::IntroductoryProgramming::Div2;
using DigiPenInstituteOfTechnology::IntroductoryProgramming::foo;

int main(void)
{
    // DigiPenInstituteOfTechnology::IntroductoryProgramming::Div2
  cout << Div2(8) << endl;             

    // DigiPenInstituteOfTechnology::IntroductoryProgramming::foo
  cout << foo << endl;             

    // Must qualify these
  cout << DigiPenInstituteOfTechnology::AdvancedProgramming::Div2(8) << endl;         
  cout << DigiPenInstituteOfTechnology::AdvancedProgramming::foo << endl;         
  
  return 0;
}
Namespace declarations are just like any other declaration in that they: This is an error (in the same scope):
using DigiPenInstituteOfTechnology::IntroductoryProgramming::Div2;
using DigiPenInstituteOfTechnology::AdvancedProgramming::Div2; // Redeclaration of Div2

Example:

namespace Stuff
{
  int foo = 11;    
  int bar = 12;    
  int baz = 13;
  int f1(int x)  { return x / 2; }
}

int foo = 21;
int bar = 22;

int f1(int x) 
{
  return x * 2;
}

int main(void)
{
  using Stuff::foo;      // similar to int foo = 11;

  int foo = 3;           // error, redefinition

  cout << foo << endl;   // Stuff::foo
  cout << bar << endl;   // ::bar

  using Stuff::bar;      // hides global bar
  cout << bar << endl;   // Stuff::bar
  cout << ::bar << endl; // global bar

  cout << f1(10) << endl;         // global f1()
  cout << Stuff::f1(10) << endl;  // Stuff::f1()

  using Stuff::f1;
  cout << f1(10) << endl;    // Now, Stuff::f1()
  cout << ::f1(10) << endl;  // global f1()

    // error, baz is undeclared
  int x = baz;  

    // should be either
  int x = Stuff::baz;

    // or
  using Stuff::baz;
  int x = baz;

  return 0;
}

Using Directives

A using directive is similar to a using declaration. A using directive allows you to make all of the names in a namespace visible at once:
using namespace Stuff;

int main(void)
{
  cout << foo << endl;  // Stuff::foo
  cout << bar << endl;  // Stuff::bar
  cout << baz << endl;  // Stuff::baz

  return 0;
}
More detailed example:
namespace Stuff
{
  int foo = 11;    
  int bar = 12;    
  int baz = 13;
}

void f1(void)
{
  int foo = 3;        // local, hides nothing
  int x = Stuff::foo; // OK
  int y = bar;        // error, bar is undeclared
}

int foo = 20;

int main(void)
{
  using namespace Stuff;

  cout << foo << endl;        // error, foo is ambiguous 
  cout << ::foo << endl;      // no problem, global
  cout << Stuff::foo << endl; // no problem, Stuff::foo

  cout << bar << endl;  // Stuff::bar
  cout << baz << endl;  // Stuff::baz

  int foo = 3;        // OK, hides Stuff::foo 
  int x = Stuff::foo; // OK, use qualified name

  return 0;
}

An example of employing using declarations and using directives

#include <iostream>
using namespace std;

namespace More {int foo = 10;}
namespace Stuff {int foo = 11;}
namespace Now {int foo = 12;}

int foo = 13;

int main(void)
{
  using namespace More;  // OK
  using namespace Stuff; // OK, no redeclaration

  cout << foo << endl;        // Error is here: now foo is ambiguous 
  cout << More::foo << endl;  // OK
  cout << Stuff::foo << endl; // OK

  using More::foo;     // OK
  cout << foo << endl; // OK, (More::foo) as if foo was declared in this scope

  using namespace Now;      // OK
  cout << foo << endl;      // OK, More::foo is still in scope
  cout << Now::foo << endl; // OK, explicitly qualified

  int foo = 3;              // Error, redefinition (collides with More::foo)
  int x = ::foo;            // OK, global foo

  return 0;
}
Suppose we remove this line above:
using More::foo;     // OK
and move the local declaration of foo to the top of the function:
int main(void)
{
  int foo = 3;           // Local declaration
  using namespace More;  // OK
  using namespace Stuff; // OK, no redeclaration
  
  . . .
}
How does this affect things?

Summary:

More examples Be sure you understand what's going on in these examples.

Design Technique Using directives were designed for backward-compatibility with existing C++ code (which doesn't understand namespaces) to help support older code. Newer code should instead use the using declarations, to prevent name collisions and ambiguity. Using declarations, especially paired with namespace aliases, give the programmer better control over the global namespace.


The Standard Namespace

Now that we've seen all the painful details of how namespaces are created and used, can you explain this common idiom?
#include <iostream>  // For cout and endl
using namespace std; // For access to *all* names inside std namespace

int main(void)
{
  cout << "Hello" << endl;
  return 0;
}
A better way to write the above:
#include <iostream> // For cout and endl;
using std::cout;    // using declaration
using std::endl;    // using declaration

int main(void)
{
  cout << "Hello" << endl;  // std::cout and std::endl
  return 0;
}
Yet another way to write code that uses the C++ standard library:
#include <iostream>  // For cout and endl

int main(void)
{
  std::cout << "Hello" << std::endl;
  return 0;
}
Now we can write code like this (to ensure job security):
#include <iostream> // For cout and endl;

int main(void)
{
  int cout = 16;  // cout is an int
  cout << 1;      // no effect
  std::cout << cout << 3 << std::endl;   // std::cout is a stream (163)
  std::cout << (cout << 3) << std::endl; // std::cout is a stream (128)
  return 0;
}