On Mon, Jan 24, 2005 at 08:15:10PM +0000, Andreas Vox wrote: > > Angus Leeming <[EMAIL PROTECTED]> writes: > > namespace support = lyx::support; > > using std::ostream; > > typedef list<string> SnippetList; > > > > is just baaaddd. > > Ah, bad for *.h, ok for *.C? > Got it.
The reason being that *.h files are included into other files in ways you cannot control. Conversely, those including a *.h file into their own code have no control over its contents (at least in principle). So, if you pull something into the global namespace in a header file, like "using std::list;" would, you force EVERY file using your header file either to use "std::list" at all times or to go through name-conflict-resolution-gymnatics to use the correct token called "list". But the whole point of namespaces is to minimize/eliminate these sorts of gymnastics in the first place. But why is it okay for *.C? First and most obviously, source files aren't included into other source or headers. But, more importantly, a source file is a "translation unit". That is, the compiler treats it (and any #include'd headers) as a self-contained entity. Any references to outside critters must be flagged as such. So, doing "using std::ostream;" inside of a source file only affects the contents of *that* source file, and only during the tokenization stage of compilation. (The compiler's gonna internally change any unqualified "ostream" tokens back into "std::ostream".) At this point, we enter a discussion of stylistics and code maintenance. The bulk of one's work on a piece of code will be maintenance, not writing it initially. It's one of the old bromides of software development, actually. Therefore, "good coding style" dictates that you "code in the future tense," using language features only in the most narrow sense. For example, you don't make all members of a class "public"; you only make those you absolutely need to expose public. In the future, should you need to expose one of your private member functions, it's trivial to do so witha quick cut-n-paste in your class header file. The idea behind a "using" clause is similar. Localize them to where you need them most, and only to there. It's not much effort to add "using std::string;" at the top of each new function that requires STL strings. Then, if you later find that, yes, most of the functions in this *.C file need STL strings and will never use any other kind of string, you can easily add a top-level "using std::string;", no changes to exsting code necessary. Consider the converse situation, where you use the hydroge-bomb approach and start out with "using std::map"; at the top of your source. You merrily write away. Then one day, you need to add a new header file and some special code for a specially-optimized RDBMS-backed dictionary structure. It's also called "map". So you write your new functions, add a "using somespecial::map" to each, and WHAMO! You get a bazillion name-conflicts at compile time. Now you not only have to remove the top-level "using std::map", but you need to sift through hundreds of lines of code to find which functions actually use std::map and add in a "using" statement to just those functions. What a headache! There are nevertheless reasons for putting a top-level "using std::foo;" decl. in a file. Doing so makes a statement: Don't even THINK of using another type of "fooXYZ" with this code! Putting in a toplevel "using std::ostream;" tells future authors that no one, no one at all, should even try to use anything but the STL ostream with this code... put it in another source file and link the two together instead! Does that help at all, Andreas? -- John Weiss