Why aren't internal namespaces private?
Or, in other words, why compile this ?:
#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 would no namespace allow internal internal include directives inside and only "export" what is actually in that namespace?
In doing so, it will work in such a way as to eliminate the need to use fully qualified names inside namespace blocks in most places, and I can't think of any drawbacks.
Does this behavior have any purpose other than making things easier for developers?
Edit:
It turns out it behaves at least somewhat sensibly, because using
there is no competition between the current namespace (B) and the included ( directive 'd) namespace (C) - the current namespace (B) always wins. However, if the current namespace (B) is included in a different location (A), then all of a sudden, B and C start competing, which should be strange for user B who didn't even know 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(); }
source to share
As far as I can tell, this feature was explicitly introduced by N0635 , suggested by Bjarne Stroustup himself. The first reason mentioned in this sentence why this feature should be introduced is because he was "repeatedly asked to do this job:"
namespace A { int f(); } using namespace A; void g() { ::f(); // call A::f }
and this one
namespace A { int f(); } namespace B { using namespace A; } void g() { B::f(); // call A::f }
According to the current rules, this does not work because it
B::f
means "look forf
declared inB
" andf
not declared inB
.
There are additional reasons mentioned in this article:
One could argue that this interpretation is closer to the way it
B::f
has always worked for the base classB
. The benefit will be the simplification of the library headers, because
namespace std { int printf(const char* ... ); // ... } using namespace std; int main() { ::printf("Hello pedantic world\n"); }
will now work. This relaxation is accepted, I would expect the standard
.h
headers to be changed to use the use directives (as originally intended) and not use-declarations. This will 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 in meaning according to the current rules, but not according to my proposed new rules. Some people are worried about changing the meaning implied by the current rules.
People responded to this proposal with remarks like "obvius", "that's what I always had in mind," and "I thought it was." I believe that an indicator that relaxation will not lead to added learning problems, but could reduce such problems.
source to share
In fact, namespaces did not exist in the original version of the C ++ programming language (1986). They were introduced later to control the logical grouping of elements. The ability to create new namespaces from other existing namespaces was part of the desired functionality (see Section 8.2.8 of the current version of Stroustrup's book).
Standard being as it is, the real question is: is using a std namespace inside your own good practice in terms of Herb Sutter's recommendation ? It will probably be safer:
// === For exposure in a header ====
namespace N{
std::string bar(); // std:: because not sure std is used in the surrounding context
void foo();
}
// === For use in the implemenation ===
using namespace std; // for the implementation
namespace N {
string bar() { return "bar";}
void foo() { cout<<"foo\n"<<bar()<<endl; }
}
The current namespace logic also has advantages. You can, for example, manage different versions of a library while still allowing legacy parts to be used during the transition by using explicit scoping.
namespace my_super_lib {
namespace my_super_lib_v1 { // legacy API
void super_f() { std::cout<<"1"; }
void super_old() {} // obsolete,
}
namespace my_super_lib_v2 { // new API
void super_f(int a) { std::cout<<"2"; }
}
using namespace my_super_lib_v2; // use now the new API
using my_super_lib_v1::super_old; // but still allow some legacy
};
The Stroutrup FAQ shows similar examples, plus a clear example for namespaces inline
.
source to share
Well, if you don't want this to happen, don't do using namespace std
or the like inside namespace N
...
It's actually quite useful sometimes to be able to "export" something from one namespace to another. Imagine I have this clever set of functions to do the flubbetiflap
functionality. For this purpose, I borrow a set of functions in the namespace kerflunk
that provides some really useful type declarations that I want to use in my functionality. So I can do:
namespace flubbetiflap
{
using namespace kerflunk;
... all the good code what I wrote to do flubbetiflap goes here ...
};
Now users of mine flubbetiflap
don't really need to know what I'm using kerflunk
for my implementation.
Of course there could be all sorts of solutions that COULD come up with for this. But I can, of course, see how this might be useful.
Obviously, no one other than the C ++ committee will learn much about the discussion that went on to determine how this should work ...
source to share