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.

Reply via email to