Does the "using" keyword have different effects in the context of defining member and non-member functions? The example code below suggests to me that it might.
main.cpp
#include "baz.h"
int main()
{
foo::bar x;
x.baz();
foo::foo_non_member();
}
baz.h
namespace foo
{
class bar
{
public:
bar() = default;
void baz();
};
void foo_non_member();
};
baz.cpp
#include "baz.h"
#include<iostream>
using namespace foo;
void bar::baz()
{
std::cout << "baz\n";
}
namespace foo
{
void foo_non_member()
{
std::cout << "non-member\n";
}
}
The above code compiles and runs.
$> g++ main.cpp baz.cpp; ./a.out
baz
non-member
If I remove the using namespace foo;
from baz.cpp, I get a compiler error.
$> g++ main.cpp baz.cpp
baz.cpp:5:6: error: ‘bar’ has not been declared
void bar::baz()
If I put that using
statement back in and move the definition of foo_non_member()
outside of the foo
namespace, I get a linker error.
$> g++ main.cpp baz.cpp
/tmp/ccHeSwsZ.o: In function `main':
main.cpp:(.text+0x24): undefined reference to `foo::foo_non_member()'
collect2: error: ld returned 1 exit status
Why does the using
keyword appear not to have the same effect here for bar::baz()
and foo_non_member()
?
For this part:
using namespace foo;
void bar::baz()
{
std::cout << "baz\n";
}
The using namespace foo;
is used for the lookup of the bar::
part, and due to that the compiler is able to tie the definition of void bar::baz()
to the declaration in the namespace foo
.
And if you remove using namespace foo;
it is not able to find bar
.
If I put that using statement back in and move the definition of foo_non_member() outside of the foo namespace, I get a linker error.
void foo_non_member()
{
std::cout << "non-member\n";
}
Here foo_non_member
not have any relation to bar::
or anything else (according to the specs) that would allow the compiler to figure out that this definition is related to the declaration in the namespace foo
.
The standard committee for sure could have added some rules to the specification to allow the compiler to get the foo_non_member
definition and the declaration together if the using namespace foo;
is present but they decided to don't do so.
The reason for that is likely because you then would have the ambiguity about whether you want to define a new void foo_non_member()
outside of the namespace foo
or if you want to have a definition for void foo_non_member()
of foo
.