http://gcc.gnu.org/bugzilla/show_bug.cgi?id=46827
Summary: Heavy use of namespaces leads to cluttered and difficult to read header files Product: gcc Version: unknown Status: UNCONFIRMED Severity: enhancement Priority: P3 Component: c++ AssignedTo: unassig...@gcc.gnu.org ReportedBy: eric-...@omnifarious.org Header files with declarations like this: void FooBar(System::Network::Win32::Sockets::Handle handle, System::Network::Win32::Sockets::Error& error /*, more fully-qualified param declarations... */); are common in certain frameworks. And using declarations, which could mitigate this problem, are generally not considered kosher to use in header files because they can effect the name lookup rules for header files that are included later. typedefs inside a class that are declared private clutter up the class' namespace and the namespace of classes derived from it. Here is a proposed solution: -------------------- using { // A 'using' block is a sort of way to fence names in. The only names // that escape the confines of a using block are names that are not // aliases for other things, not even for things that don't have names // of their own. These are things like the declarations for new // classes, enums, structs, global functions or global variables. // New, non-alias names will be treated as if they were declared in // the scope in which the 'using' block appeared. using namespace ::std; using ::mynamespace::mytype_t; namespace mn = ::mynamespace; using ::mynamespace::myfunc; class AClass { public: typedef mytype_t atype_t; AClass(const string &st, mytype_t me) : st_(st), me_(me) { myfunc(&me_); } private: const string st_; mn::mytype_t me_; }; typedef struct { int a; } simple; // The effects of all typedefs, using declarations, and namespace // aliases that were introduced at the level of this block go away // here. typedefs and using declarations inside of nested classes // or namespace declarations do not go away. } // end using. // Legal because AClass is treated as having been declared in this // scope. AClass a("Fred", ::mynamespace::mytype_t(5)); // Not legal, alias mn no longer exists. AClass b("Fred", mn::mytype_t); // Not legal, the using directive bringing in mytype_t is no longer in effect AClass b("Fred", mytype_t); // Not legal, the using directing bringing in myfunc is no longer in effect. AClass c("Fred", myfunc(::mynamespace::mytype_t(5)); // Legal, only names declared at level of the using block disappear. names // declared in nested sub-blocks (like namespace or class declarations) do not. AClass d("Fred", AClass::atype_t(5)); // Not legal, the name simple, being an alias for an anonymous structure, // disappeared at the end of the using block. simple e; -------------------- Java, Python and other languages have ways of bringing in names from other namespaces with a very limited scope. In Java, the import directive brings in a name that only exists for the duration of the .java file. In Python, the import statement can bring names into a module from outside, and it's relatively easy to prevent those names from being easily exported outside the module. C++ needs a similar mechanism. The existence of the preprocessor the #include directive and the C++ concept of a translation unit make the implicit scoping of imported names problematic. So some mechanism for explicitly scoping such temporary aliases is needed. Hence my above proposal of the 'using' block.