1

I am trying to access variable x using using directive in the following code:

#include <iostream>
using namespace std;
int x = 10;
namespace e {
int x = 5;
}
int main() {
using namespace e; // Because of this line compiler shows error
cout << x;
return 0;
}

In general we use the following line to access x but I am getting error We can also use using e::x; But my question is why can't we use using namespace e;

BethBorgov
  • 13
  • 3
  • 1
    Note, the error is not on the line you pointed, but one below. If you have `using namespace e;`, how can compiler distinguish between `::x` and `::e::x`? – Yksisarvinen Jan 14 '21 at 12:43
  • Can u please explain clearly as I am learning this topic for the first time? – BethBorgov Jan 14 '21 at 12:46
  • Does this answer your question? [Why and how should I use namespaces in C++?](https://stackoverflow.com/questions/4211827/why-and-how-should-i-use-namespaces-in-c) – Federico Baù Jan 14 '21 at 12:51
  • These 2 answer may help you out!: [Why and how should I use namespaces in C++?](https://stackoverflow.com/questions/4211827/why-and-how-should-i-use-namespaces-in-c) & [What exactly is a namespace and why is it necessary](https://stackoverflow.com/questions/32161199/what-exactly-is-a-namespace-and-why-is-it-necessary) – Federico Baù Jan 14 '21 at 12:52
  • I don't think so – BethBorgov Jan 14 '21 at 12:54

2 Answers2

1

In this example it may seem that using namespace e; makes names from namespace e available in main function scope. However it does not do this. Instead it tries to inject names (during unqulified lookup in main) from namespace e into the nearest enclosing namespace of main and namespace e, to the global namespace that is. Therefore x becomes ambiguous.

user7860670
  • 35,849
  • 4
  • 58
  • 84
0

Let's start with another example.

const int x = 10;

namespace e {
const int y = 5;
}

int main()
{
std::cout << e::y;
using namespace e;
std::cout << y;
}

There is variable with value 10 and name x in global namespace (which can be referred to as x simply) and variable with value 5 with name y in namespace e (which must be referred to as e::y).

By adding using namespace e;, you inject all names from namespace e into global namespace. This means global namespace now contains names x and y, and namespace e contains name y. You can now refer to variable with value 5 using both y and e::y.

Now, back to your example. If we change y to x:

const int x = 10;

namespace e {
const int x = 5;
}

int main()
{
std::cout << e::x;
using namespace e;
std::cout << x;
}

There is x in global namespace and x in namespace e. By adding using namespace e; you inject all the names from namespace e to global namespace, so now global namespace contains names x and x, and namespace e contains name x. See the problem? Global namespace contains two names x, which confuses the compiler. When you try to print variable under the name x, compiler looks up names in global namespace and finds two x. It cannot choose which one you meant, so it throws error.

This is the main reason why using namespace (particularly using namespace std;) is considered evil. One can easily break working code by updating a library or introducing a new function. Compiler error is best outcome in such a case, but sometimes it's possible that compiler will silently replace one function by another, because it matches better.

You can still access both variables using fully qualified names:

int main()
{
using namespace e;
std::cout << ::x << " "; //x from global with fully quafilied name
std::cout << ::e::x << " "; //x from namespace e with fully qualified name
std::cout << e::x; //not fully qualified, but not ambiguous either - only one x in namespace e
}
Yksisarvinen
  • 18,008
  • 2
  • 24
  • 52