After reading The C++ Programming Language 4th edition (section 14.4.4 - Composition and Selection) I thought that the following program would compile correctly:
#include <iostream>
namespace foo {
int var = 0;
// more declarations
}
namespace bar {
int var = 1;
// more declarations
}
namespace baz {
// composition of namespaces foo and bar
using namespace foo;
using namespace bar;
// I thought that the following line would resolve the name clash
using foo::var;
}
using namespace baz;
void qux(int n) {
if (n == var) {
std::cout << "baz: var " << std::endl;
} else {
std::cout << "baz: " << n << std::endl;
}
}
int main() {
qux(0);
qux(1);
}
The expected output should be
baz: var
baz: 1
When I try to compile the code above I get an error saying that the reference to 'var' is ambiguous. Using foo::var
eliminates the compilation error but I would like to better understand this problem.
What is wrong in my code?
How can I resolve the name clash in a way that the namespace baz contains foo::var
?
Thanks!
EDIT
As suggested in the answers below, moving the definition of qux
inside the namespace baz
makes it valid. Therefore, the following code compiles as expected
#include <iostream>
namespace foo {
int end = 0;
}
namespace bar {
int end = 1;
}
namespace baz {
using namespace foo;
using namespace bar;
using foo::end;
void qux(int n) {
if (n == end) {
std::cout << "baz: end " << std::endl;
} else {
std::cout << "baz: " << n << std::endl;
}
}
}
int main() {
baz::qux(baz::end);
baz::qux(1);
}
There is still one thing which is not completely clear to me. I thought that adding using namespace baz
would make everything in baz
available also in the current scope without using baz::
. In other words, I would have expected that since "everything works in the namespace baz" this would be true also in the current scope after adding using namespace baz
.
// I thought that the following line would resolve the name clash using foo::var;
Well, it does resolve the name clash for the current namespace, which is baz
.
If you move qux
into baz
, it will prefer foo::var
.
But for ::qux
(outside any namespace), there is no reason to prefer baz::var
(the alias for foo::var
) over bar::var
or foo::var
, since all of them are in the current namespace search path.
Even though only using namespace baz;
was seen at global level.