Namespaces - Examples


This code is fine:

#include <iostream> 
using namespace std;

namespace Stuff
{
  int foo = 11;  // Stuff::foo    
  int bar = 12;  // Stuff::bar
}

int foo = 21;  // global, (Also Known As ::foo)
int bar = 22;  // global, (Also Known As ::bar)

void f1(void)
{
  cout << foo << endl;        // unqualified, global (::foo), 21
  cout << Stuff::foo << endl; // qualified, Stuff::foo, 11 
}

int main(void)
{
  cout << foo << endl;        // unqualified, global, 21
  cout << ::foo << endl;      // qualified, global, 21
  cout << Stuff::foo << endl; // qualified, Stuff::foo, 11
  return 0;
}

Notice the using directive and its placement:

namespace Stuff
{
  int foo = 11;  // Stuff::foo    
  int bar = 12;  // Stuff::bar
}

using namespace Stuff;  // foo is now an alias for Stuff::foo
                        
int foo = 21;  // global, ::foo
int bar = 22;  // global, ::bar

void f1(void)
{
  cout << foo << endl;        // unqualified, ambiguous: global (::foo) or alias (Stuff::foo)?
  cout << Stuff::foo << endl; // qualified, Stuff::foo, 11 
}

int main(void)
{
  cout << foo << endl;        // unqualified, ambiguous: global (::foo) or alias (Stuff::foo)?
  cout << ::foo << endl;      // qualified, global, 21
  cout << Stuff::foo << endl; // qualified, Stuff::foo, 11
  return 0;
}

The same using directive is moved and produces different results:

namespace Stuff
{
  int foo = 11;  // Stuff::foo    
  int bar = 12;  // Stuff::bar
}

int foo = 21;  // global, ::foo
int bar = 22;  // global, ::bar

void f1(void)
{
  cout << foo << endl;        // unqualified, global (::foo), 21
  cout << Stuff::foo << endl; // qualified, Stuff::foo, 11 
}

using namespace Stuff;  // foo is now an alias for Stuff::foo
                        // bar is now an alias for Stuff::bar
                        
int main(void)
{
  cout << foo << endl;        // unqualified, ambiguous: global (::foo) or alias (Stuff::foo)?
  cout << ::foo << endl;      // qualified, global, 21
  cout << Stuff::foo << endl; // qualified, Stuff::foo, 11
  return 0;
}

The same using directive is placed within a function (scope is only in the function):

namespace Stuff
{
  int foo = 11;  // Stuff::foo    
  int bar = 12;  // Stuff::bar
}

int foo = 21;  // global, ::foo
int bar = 22;  // global, ::bar

void f1(void)
{
  using namespace Stuff;  // foo is now an alias for Stuff::foo
                          // bar is now an alias for Stuff::bar
                        
  cout << foo << endl;        // unqualified, ambiguous: global (::foo) or alias (Stuff::foo)?
  cout << Stuff::foo << endl; // qualified, Stuff::foo, 11 
}

int main(void)
{
  cout << foo << endl;        // unqualified, global (::foo), 21
  cout << ::foo << endl;      // qualified, global, 21
  cout << Stuff::foo << endl; // qualified, Stuff::foo, 11
  return 0;
}

The same using directive is placed in main after some code:

namespace Stuff
{
  int foo = 11;  // Stuff::foo    
  int bar = 12;  // Stuff::bar
}

int foo = 21;  // global, ::foo
int bar = 22;  // global, ::bar

void f1(void)
{
  cout << foo << endl;        // unqualified, global (::foo), 21
  cout << Stuff::foo << endl; // qualified, Stuff::foo, 11 
}

int main(void)
{
  cout << foo << endl;        // unqualified, global (::foo), 21
  cout << ::foo << endl;      // qualified, global, 21
  cout << Stuff::foo << endl; // qualified, Stuff::foo, 11

  using namespace Stuff;  // foo is now an alias for Stuff::foo
                          // bar is now an alias for Stuff::bar
                        
  cout << foo << endl;    // unqualified, ambiguous: global (::foo) or alias (Stuff::foo)?
  
  int foo = 41;           // local, hides alias from Stuff::foo
  cout << foo << endl;    // unqualified, local, 41
  cout << ::foo << endl;  // qualified, global (::foo), 21

  return 0;
}

Now, we are employing the using declaration, and we get very different behavior:

namespace Stuff
{
  int foo = 11;  // Stuff::foo    
  int bar = 12;  // Stuff::bar
}

using Stuff::foo; // declare foo (from Stuff) here in global namespace
                  //   (it's now the global ::foo)!

int foo = 21;  // error, redefinition, foo already declared (must remove this to compile)
int bar = 22;  // global, (Also Known As ::bar)

void f1(void)
{
  cout << foo << endl;        // unqualified, global (::foo aka Stuff::foo), 11
  cout << Stuff::foo << endl; // qualified, Stuff::foo, 11 
}

void f2(void)
{
  int foo = 31;               // local, hides global (OK, declaration at different scope)
  cout << foo << endl;        // unqualified, local, 31
  cout << Stuff::foo << endl; // qualified, Stuff::foo, 11 
}

int main(void)
{
  cout << foo << endl;        // unqualified, global (::foo aka Stuff::foo), 11
  cout << ::foo << endl;      // qualified, global (::foo aka Stuff::foo), 11 
  cout << Stuff::foo << endl; // qualified, Stuff::foo, 11

  int foo = 41;           // local, hides alias Stuff::foo (OK, declaration at different scope)
  cout << foo << endl;    // unqualified, local, 41
  cout << ::foo << endl;  // qualified, global (::foo aka Stuff::foo), 11

  return 0;
}

Move using declaration into a new scope (in main):

namespace Stuff
{
  int foo = 11;  // Stuff::foo    
  int bar = 12;  // Stuff::bar
}

int foo = 21;  // global, (Also Known As ::foo)
int bar = 22;  // global, (Also Known As ::bar)

void f1(void)
{
  cout << foo << endl;        // unqualified, global ::foo, 21
  cout << Stuff::foo << endl; // qualified, Stuff::foo, 11 
}

void f2(void)
{
  int foo = 31;               // local, hides global (OK, declaration at different scope)
  cout << foo << endl;        // unqualified, local, 31
  cout << Stuff::foo << endl; // qualified, Stuff::foo, 11 
}

int main(void)
{
  cout << foo << endl;        // unqualified, global (aka ::foo), 21
  cout << ::foo << endl;      // qualified, global ::foo, 21 
  cout << Stuff::foo << endl; // qualified, Stuff::foo, 11
  
  using Stuff::foo; // declare foo (from Stuff) here locally to main

  int foo = 41;           //error, redefinition, foo already declared in this scope (remove to compile)
  cout << foo << endl;    // unqualified, local (aka Stuff::foo), 11
  cout << ::foo << endl;  // qualified, global (::foo), 21
  
  return 0;
}