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(); }

      

+3


source to share


3 answers


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 for f

declared in B

" and f

not declared in B

.



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 class B

. 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.

+2


source


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

.

+1


source


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 ...

0


source







All Articles