Pergunta

I generally like to organize classes I make into modules by using namespaces, and I also don't go more than 2 namespaces deep but it's still painstakingly hard to fully qualify everything.

I've thought of using using directives but I don't want some headers polluting other headers. For example:

MyHeader1.hpp

namespace MyLibrary {
    namespace MyModule1 {
        class MyClass1 {
            // stuff
        };
    } // namespace MyModule1
} // namespace MyLibrary

MyHeader2.hpp

namespace MyLibrary {
    namespace MyModule2 {
        // I can import stuff
        // using namespace MyLibrary::MyModule1;
        // using MyLibrary::MyModule1::MyClass1;

        class MyClass2 {
        public:
            void DoSomething(MyLibrary::MyModule1::MyClass1 parameter); // I could do this
            void DoSomething(MyClass1 parameter); // or this (easier)
        };
    } // namespace MyModule2
} // namespace MyLibrary

MyHeader3.hpp

#include <MyModule2/MyHeader2.hpp>

namespace MyLibrary {
    namespace MyModule2 {
        // I understand that MyClass3 may use MyClass1 from here (the using directive would be beneficial), but what if it doesn't; it's left hanging in here import-ed
        // I can see MyLibrary::MyModule1::MyClass1 from here!

        class MyClass3 {
            MyClass2 some_var;
        };
    } // namespace MyModule 2
} // namespace MyLibrary

The "problem" here is that I can see MyClass1 in MyHeader3.hpp inside the MyModule2 namespace if I import it inside MyHeader2.hpp. I can see that this would not be a problem if using directives were allowed at class scope.

Question is, is there a better way of doing this, should I just man up and fully-qualify everything or should I avoid namespaces altogether?

Foi útil?

Solução

No, you should definetely not abandom namespaces! Instead, you should organize your code better, and maybe check your architecture again.

First, you should not use using namespace MyLibrary::MyModule1; or using MyLibrary::MyModule1::MyClass1; in a header, to avoid namespace polution, since there is no way to undo that (see this question and answers).

Another option is to use typedefs :

namespace MyLibrary {
    namespace MyModule2 {

        class MyClass2 {
        public:

            typedef MyLibrary::MyModule1::MyClass1 FunctionArg;

            void DoSomething(FunctionArg parameter);
        };
    } // namespace MyModule2
} // namespace MyLibrary

And if you use c++11 and later, you can use using in another way :

namespace MyLibrary {
    namespace MyModule2 {

        class MyClass2 {
        public:

            using  FunctionArg=MyLibrary::MyModule1::MyClass1;
            void DoSomething(FunctionArg parameter);
        };
    } // namespace MyModule2
} // namespace MyLibrary
Licenciado em: CC-BY-SA com atribuição
scroll top