Question

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?

Était-ce utile?

La solution

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
Licencié sous: CC-BY-SA avec attribution
scroll top