Or in other words, why allow this to compile?:
#include <iostream>
namespace N{
using namespace std;
string bar() { return "bar";}
void foo() { cout<<"foo\n"<<bar()<<endl; }
}
int main(){
N::foo();
N::cout<<">why allow this??\n"; //Can't ::N:: keep `::std::` to itself?
}
Why not have each namespace resolve its inner include directives internally and only "export" what's actually in that namespace?
Making it work like that would eliminate the need to use fully qualified names inside namespace blocks in most places and I can't think of the drawbacks.
Does this behavior have any purpose besides making things possibly easier on implementers?
Edit:
Turns out it behaves at least somewhat sensible in that there's no contention between a current namespace (B) and an included (using directive'd) namespace (C)—the current namespace (B) always wins. However if the current namespace (B) is included elsewhere (A) then suddenly, the suddenly, B and C start competeting, which must be weird for the user of B who never even knew about C:
#include <iostream>
namespace C {
void method() { std::cout<<"C\n"; }
void cmethod() { std::cout<<"cmethod\n"; }
}
namespace B { using namespace C;
void method() { std::cout<<"B\n"; } }
///^^Library
///>User code
namespace A {
using namespace B;
void aMethod() {
//method(); Error:
//conflict between B::method and C::method even though A doesn't even know about C
B::method(); //Why do I need to write this when I just included B?
cmethod(); //This simply leaks from C because of the u-directive
}
}
int main() { A::aMethod(); }
As far as I can tell, this feature has been explicitly introduced by N0635, proposed by Bjarne Stroustrup himself. The first reason mentioned in that proposal why this feature should be introduced is because he has been "repeatedly asked to make this work:"
namespace A { int f(); } using namespace A; void g() { ::f(); // call A::f }and this
namespace A { int f(); } namespace B { using namespace A; } void g() { B::f(); // call A::f }Under the current rules, this doesn’t work because
B::fmeans "look for anfdeclared inB" andfisn’t declared inB.
There are additional reasons mentioned in that paper, though:
One could argue that this interpretation is closer to the way
B::falways worked for a base classB. A benefit would be a simplification of the library headers becausenamespace std { int printf(const char* ... ); // ... } using namespace std; int main() { ::printf("Hello pedantic world\n"); }would now work. It this relaxation is accepted, I would expect the standard
.hheaders to be changed to use using-directives (as originally intended) rather than using-declarations. This would save hundreds of lines of declarations.Also, if someone takes
static void f(char); void f(int); void g() { ::f(’a’); // calls f(char) }and naively translates it to
namespace { void f(char); } void f(int); void g() { ::f(’a’); // current rules: class f(int) // relaxed rules: calls f(char) }then there would be a change of meaning under the current rules, but not under my suggested new rules. Some people have worried about the change of meaning implied by the current rules.
People have responded to this proposal with remarks like "obvius," "that was what I always meant," and "I thought that was what it did." I consider that an indicator that the relaxation will not lead to added teaching problems, but might reduce such problems.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With