web-dev-qa-db-ja.com

別の名前空間内に名前空間をインポートする

私は通常、名前空間を使用して、作成するクラスをmodulesで整理するのが好きです。また、名前空間の深さは2を超えませんが、すべてを完全に修飾することは依然として困難です。

singディレクティブを使用することを考えましたが、一部のヘッダーが他のヘッダーを汚染したくありません。例えば:

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

ここでの「問題」は、MyClass1内にインポートすると、MyHeader3.hpp名前空間内のMyModule2内にMyHeader2.hppが表示されることです。 singディレクティブがクラススコープで許可されている場合、これは問題にならないことがわかります。

質問は、これを行うより良い方法はありますか?私はすべてを完全に修飾し、名前空間を完全に避けるべきですか?

8

いいえ、明確に名前空間を放棄するべきではありません!代わりに、コードを適切に整理し、おそらくアーキテクチャを再度確認する必要があります。

まず、using namespace MyLibrary::MyModule1;またはusing MyLibrary::MyModule1::MyClass1;ヘッダーで、名前空間の汚染を回避するため。ヘッダーを元に戻す方法はありません( この質問と回答 を参照)。

別のオプションはtypedefsを使用することです:

namespace MyLibrary {
    namespace MyModule2 {

        class MyClass2 {
        public:

            typedef MyLibrary::MyModule1::MyClass1 FunctionArg;

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

また、c ++ 11以降を使用している場合は、usingを別の方法で使用できます。

namespace MyLibrary {
    namespace MyModule2 {

        class MyClass2 {
        public:

            using  FunctionArg=MyLibrary::MyModule1::MyClass1;
            void DoSomething(FunctionArg parameter);
        };
    } // namespace MyModule2
} // namespace MyLibrary
11
BЈовић