TITLE: namespace organization suggestion (Newsgroups: comp.lang.c++.moderated, 2 Dec 97) ABRAHAMS: David Abrahams I'm still looking for a good set of guidelines for using namespaces. Since recent postings I've come up with a few insights, but haven't settled all issues. Further discussion/comments would be appreciated. I'd especially like to hear from anyone with practical experience in this area. 1. Namespace organization The best way I can imagine for organizing a namespace is to have a central repository that contains declarations (not neccessarily complete) of all names in the namespace: // N.h namespace N { class X; class Y; class Z; const int k = 3; } // X.h #include "N.h" class N::X { ... }; // Complete definition of X // Y.h #include "N.h" namespace N { class Y { ... }; // Complete definition of Y } The method used in Y.h above may be more convenient, but in order to preserve the integrity of this scheme care must be taken not to introduce any new declarations to N in Y.h which aren't already in N.h. Why do I like this scheme? It makes using-directives more reliable. The alternative is a world where the set of names in a namespace varies with the translation unit: //A.h namespace M { class A {...}; } //B.h namespace M { class B {...}; } // BB.h namespace L { class B {...}; } //Q.cpp #include "Q.h" #include "A.h" void foo() { using namespace M; // M declared in A.h -- OK. B b; // Which definition of B is this? Depends on what Q.h #includes. } In previous posts I raised the issue of template name resolution, but after a little while I realized that the problem has nothing to do with templates. The program above is subject to wild semantic changes due to possibly subtle shifts in the header file dependency chain for Q.h. The alternatives seem to be: a. Eschew using-directives and hope that your code's clients do the same. b. Adopt this organization and stick to it rigorously 2. Classic idioms Lots of my legacy header files look like this: // R.h #include "D.h" // Definitions required in order to #include "E.h" // parse R's definition #include "F.h" class G; // forward declare classes used by reference class H; // or pointer. class R { void f1( const G& ); void f2( H* ); D m1; E m2; F m3; }; This is a common way to minimize recompilation dependencies. What happens to this file when G and H are in some non-global namespace scope K? There are 2 alternatives: // K.h -- as in my proposed scheme above namespace K { class G; class H; // other declarations here -- lots of them. }; // R.h #include "D.h" // Definitions required in order to #include "E.h" // parse R's definition #include "F.h" #include "K.h" // All names declared in K, no other forward // declarations needed. class R { void f1( const K::G& ); void f2( K::H* ); ... }; - OR - // R.h #include "D.h" // Definitions required in order to #include "E.h" // parse R's definition #include "F.h" namespace K { class G; // forward declare G and H in K class H; } class R { ... }; // As above In the first alternative, I have introduced a compile-time dependency of R on the entire set of names defined in K. In the second K's client, R, has a good chance of *unintentionally* defining new names in K, which could affect the semantics of any of R's clients which "use" K. I'm not too happy with the choices I have here, but I guess I'd choose the first one. It relies on cooperation from clients of K, but less so than the second one. I'd like a bit more protection from the core language, but I'm not sure just what that would look like. I seem to be gravitating towards treating namespaces like class scopes (which require all names to be defined contiguously) -- since we can't write "using class X". Anyway, the core language is settled for some time to come, so I really need a way to coexist with it. At my company we're regarding namespaces with suspicion until we get this figured out.