
#include <iostream>

namespace A
{
	int paul = 11;
	int fred = 111;

	namespace B
	{
		int paul = 22;
		int fred = 222;
		int ulla = 2222;
	}
	
	// confusing, but possible: same namespace name nested within!
	namespace A
	{
		int paul = 8;
		int fred = 88;
	}

}

namespace C
{
	int paul = 33;
}

namespace D
{
	using C::paul;
	using A::B::ulla;
}


using std::cout;

int main ()
{

	cout << "A::paul = " << A::paul << std::endl;
	cout << "A::B::paul = " << A::B::paul << std::endl;
	cout << "C::paul = " << C::paul << std::endl;

	// Not found!
	// cout << "paul = " << paul << std::endl;

	using namespace A;
	cout << "paul = " << paul << std::endl;

	using ::A::B::paul;
	// A::B::paul takes precedence due to the previous "using declaration".
	cout << "paul = " << paul << std::endl;

	// Must not overdo it - paul would become ambiguous
	// using C::paul;
	// cout << "paul = " << paul << std::endl;

	// Even though there is no A::A::B, this would not work
	// (Given the "using namespace A;" declaration above!)
	// using namespace A::B;
	
	// We can disambiguate by prefixing ::
	// The ::A tells that we want to refer to "top level".
	using namespace ::A::B;

	// Now fred is ambiguous:  A::fred or A::B::fred ?
	// Fortunately, as long as we are not using it, there is no issue.
	//
	// cout << "fred = " << fred << std::endl;

	// Just to make the nonsense complete ;-)
	using namespace ::A::A;

	// Ambiguous!  namespace A{} or namespace A::A{} ?
	// cout << "A::paul = " << A::paul << std::endl;
	// cout << "A::A::paul = " << A::A::paul << std::endl;
	
	// We can always disambiguate explicitly.
	cout << "::A::paul = " << ::A::paul << std::endl;
	cout << "::A::A::paul = " << ::A::A::paul << std::endl;

	// namespaces can "import" from each other
	cout << "D::paul = " << D::paul << std::endl;
	cout << "D::ulla = " << D::ulla << std::endl;
	cout << "B::ulla = " << B::ulla << std::endl;

	using namespace D;

	// Note: ulla can be accessed through ::A::B::ulla or ::D::ulla,
	// but since ::D::ulla is actually ::A::B::ulla, there is no abibuity here
	cout << "ulla = " << ulla << std::endl;

	return 0;
}


