// NamespaceTutorial.cpp

// The primary purpose of this program i

//     s to demonstrate the use and value of na

//     mespaces.

// Also touched on is using the STL stri

//     ng container and typedef.

// In a small program written and mainta

//     ined by a small number of people namespa

//     ce problems

// are less likely to arise. However in 

//     large programs maintained by many people

//     over long

// periods of time or by anyone developi

//     ng reusable libraries of code, namespace

//     is a very

// important aspect of programming.

// Okay so what the heck are talking abo

//     ut when we say namespace. Well namespace

//     parallels

// scope for variable names except inste

//     ad of variables we mean function names. 

//     Variable

// scope allows you reuse a variable nam

//     e for different variable even while anot

//     her variable

// with that name exists at the same tim

//     e in a different scope.

// For example:

// void funcA (int first, int second);

// void funcB (int first, int second);

// void funcC (int first, int second);

// In the above we have three different 

//     functions each of which will internally 

//     reference

// a different variables first and secon

//     d than any of the others. Otherwise we w

//     ould have

// serious problems with the values of t

//     hose variables being changed in unpredic

//     table and 

// uncontrolled ways.

// In a similiar way if Bob writes a lib

//     rary and somewhere else in the world Joe

//     writes a

// completely different library. Somewhe

//     re else Kevin wants to incorporate the h

//     ard work

// of these two people into his own code

//     and save lots of time, but there is a pr

//     oblem. Both

// Bob and Joe have several functions wi

//     th the same name: Initialize(), Reinitia

//     lize(), Output(),

// Configure(), Transform(), etc. This e

//     nds up creating many headaches for Kevin

//     who doesn't

// save as much time as he had hoped to.

//     Now if the authors of those libraries ha

//     d used a

// namespace in defining their library t

//     hen Kevin could of indicated which funct

//     ion he was

// referring to without fear.

// This principal also works for Classes

//     so that within the namespace of your lib

//     rary you can

// use Class names that make sense and d

//     on't include a bunch goobley-gook. Inste

//     ad of using 

// a class called MyWSASocketClass, you 

//     can use a namespace "MyWSA" and a class 

//     named Socket.

// In the code below the functions are v

//     ery simple and while conceptually relate

//     d to each

// other, in real code this would not li

//     kely be the case. In fact in the below f

//     unctions would

// more likely be written as a member fu

//     nctions of classes. Please forgive me an

//     d look at the

// below code in a structural sense, rat

//     her than looking at the names of the nam

//     espaces I use.

// The names were changed to protect the

//     innocent and have no real bearing on the

//     topic other

// than to expedite a sense of what func

//     tion is getting called. 

// Note that these headers look differen

//     t than normal headers

// A normal header would look like: <

//     string.h> or 

// The use of the these particular heade

//     rs indicates that we are using the std n

//     amespace

// header for these functions, rather th

//     an the older non-namespace headers.

#include 

#include 

// The word "using" is a directive. It t

//     ells the compiler that when referring to

//     a something

// named string we want it to look in th

//     e namespace std first. It is useful to n

//     ote that if 

// string is used in a way that is not d

//     efined in the std namespace it will look

//     elsewhere for it.

using std::string;

// Here we create an alias for the std n

//     amespace. I admit that typically you are

//     not going to

// create an alias that is even bigger t

//     han the original namespace but it illust

//     rates this

// ability without overly contriving the

//     code. From this point on we can to the s

//     td namespace

// using std or standard names. The nice

//     thing about this is that library authors

//     can use larger

// more descriptive namespace names that

//     are very unlikely to cause names clashes

//     , and the 

// programmer using the library can crea

//     te an alias for the namespace within a s

//     cope that is not 

// going to create name clashes. For exa

//     mple a library author could use the foll

//     owing namespace:

// namespace felan7476099_hotmail_com_Wi

//     ndowsSocket;

// The users of this library within func

//     tion that call upon the library create a

//     n alias:

// namespace WinSock = felan7476099_hotm

//     ail_com_WindowsSocket;

namespace standard = std;

// Here we create a function called Cham

//     pion() but we do in a namespace of King.

//     

namespace King

    {

     void Champion()

         {

         std::cout << "This is the King's Champion" << std::endl;

         }

    }

    // Here we create a function called Cham

    //     pion() within a namespace of Queen.

    namespace Queen

        {

         void Champion()

             {

             // this line makes all functions from the std namespace available for use within

             // this function only. This allows us to use cout and endl without explicitly

             // specifying the std namespace. It is considered poor programming practice to

             // do this globally as it defeats the solution namespaces provide. It is possible

             // to have several "using namespace" directives in the same function. if you do

             // have several "using namespace" directives you can still use the namespace and

             // scope resolution operator to indicate which namespace's function you want to 

             // use in the case of overlapping function names.

             using namespace std;

             cout << "This is the Queen's Champion" << endl;

             }

        }

        // This Champion() function is declared 

        //     with no namespace and would conflict wit

        //     h the

        // Champion() functions in the King and 

        //     Queen namespaces if those function were 

        //     not in

        // the those namespaces.

        void Champion()

            {

             std::cout << "This is a unaffliated Champion" << std::endl;

        }

        // This function uses the using directiv

        //     e to indicate which Champion() function 

        //     should be

        // used. 

        void Champions()

            {

             // this directive says that in this scope for the Champion() function only use the King

             // namespace. this directive allows to use the shorter form of Champion() to call the

             // same function we would call using King::Champion(). In this function block this is

             // trivial as we only call Champion once, however in a large function Champion() could 

             // get called many many many times and this directive makes it much simplier to call

             // the function we want.

             using King::Champion;

             // Since we are using the King namespace this function is effectively King::Champion()

             Champion();

             Queen::Champion();

             // Since we are in the King namespace calling Champion() would get us King::Champion()

             // but we want the Champion() declared in the global namespace, so we use the scope

             // resolution operator with no namespace.

             ::Champion();

        }

        // The first argument is of the type str

        //     ing&, which resolves to the same templat

        //     e class as the

        // std::string& thanks to the earlier "u

        //     sing std::string;" directive we used. 

        void OutputTestStrings(const string& testa, const std::string& testb)

            {

             std::cout << testa << std::endl << testb << std::endl << std::endl;

        }

        int main(int argc, char* argv[])

            {

             std::string testa = "Test of std::string";

             string testb = "Test of string";

             standard::cout << "After creating the strings" << standard::endl;

             OutputTestStrings(testa, testb);

             testa = testb;

             std::cout << "After assigning testb to testa" << std::endl;

             OutputTestStrings(testa, testb);

             std::cout << "Call on the King" << std::endl;

             King::Champion();

             std::cout << std::endl;

             std::cout << "Call on the Queen" << std::endl;

             Queen::Champion();

             std::cout << std::endl;

             std::cout << "Call on a stranger" << std::endl;

             Champion();

             std::cout << std::endl;

             std::cout << "Call on a couple of Champions" << std::endl;

             Champions();

             std::cout << std::endl;

             return 0;

        }