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, the compiler shows an error
cout << x;
return 0;
}
In general, we use the following line to access x
, but I am getting an error.
We can also use using e::x;
, but my question is why can't we use using namespace e;
.
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 a variable under the name x
, the 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. A compiler error is the best outcome in such a case, but sometimes it's possible that the 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
}