Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Scoped using-directive within a struct/class declaration? [duplicate]

I find that my C++ header files are quite hard to read (and really tedious to type) with all the fully-qualified types (which goes as deep as 4 nested namespaces). This is the question (all the answers give messy alternatives to implementing it, but that's not the question): Is there a strong reason against introducing scoped using-directive in structs and classes in the C++ language (while it's permissible to have scoped using-declaration in functions)?

e.g.

class Foo : public Bar {     using namespace System;     using namespace System::Network;     using namespace System::Network::Win32::Sockets;     using Bar::MemberFunc; // no conflict with this      // e.g. of how messy my header files are without scoped using-directive     void FooBar(System::Network::Win32::Sockets::Handle handle, System::Network::Win32::Sockets::Error& error /*, more fully-qualified param declarations... */); }; 

Since namespace is a keyword, I would've thought it's distinct enough to cause no conflict with the scoped using declaration such as Bar::MemberFunc.

EDIT: Read the question carefully ---> I've bolded it. Reminder: we're not discussing how to improve readability of the example here. Suggesting how scoped using-directive could be implemented (i.e. by means of adding keywords / constructs etc.) in the C++ language is NOT an answer (if you could find an elegant way to implement this using existing C++ language standards, then it would of course be an answer)!

like image 779
Zach Saw Avatar asked Dec 06 '10 03:12

Zach Saw


2 Answers

Sometimes I do this to achieve almost the same effect:

namespace detail {     using namespace System;     using namespace System::Network;     using namespace System::Network::Win32::Sockets;      class Foo : public Bar     {          void FooBar(Handle handle, Error& error);     }; } using detail::Foo; 
like image 93
Timo Avatar answered Sep 25 '22 14:09

Timo


Given that using declarations at class scope are not inherited, this could work. The name would only be valid inside that class declaration, or inside the declarations of nested classes. But I think it's sort of overloading the concept of a class with an idea that should be larger.

In Java and Python individual files are treated in a special way. You can have import declarations that inject names from other namespaces into the file. These names will (well, not exactly with Python, but it's too complicated to explain here) only be visible within that file.

To me that argues for this sort of ability not being tied to a class declaration, but given a scope of its own instead. This would allow injected names to be used in several class declarations if it made sense, or even in function definitions.

Here is an idea I prefer because it allows these things while still giving you the benefits of a class level using declaration:

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:       AClass(const string &st, mytype_t me) : st_(st), me_(me) {          myfunc(&me_);       }       private:       const string st_;       mn::mytype_t me_;    }; // 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 unqualified name myfunc no longer exists. AClass c("Fred", myfunc(::mynamespace::mytype_t(5)); 

This is analogous to declaring a block for local variables in a function. But in this case you are declaring a very limited scope in which you will be changing the name lookup rules.

like image 31
Omnifarious Avatar answered Sep 22 '22 14:09

Omnifarious