6

パッケージ化されたコードで名前空間を使用するための最良/最もクリーンな方法は何ですか?

たとえば、ブーストのようなライブラリでは、非常に組織化された名前空間管理があるようです。名前を明確にするためにいくつかの手法が使用されています。ただし、重要なことは、次のようなコードはあまり表示されないということです。

typedef namespace1::namespace2::sth_else::a_class<namespace3::namespace4::b_class> type;

通常、クロスネームスペースはあまりありません。これは、優れたアーキテクチャだけでなく、優れた名前空間管理も示しています。問題は、優れた名前空間管理とは何かということです。

次のようなファイル構造があるとします。

component1/...  (depends on reusable_if)
component2/...  (depends directly on reusable_if and on component 1)
reusable/
reusable/some_part/
reusable/some_part/...
reusable/some_other_part/
reusable/some_other_part/...
reusable/SthThatUsesBothReusableParts.h   (implements reusable_if/ISth.h)
reusable/SthThatUsesBothReusableParts.cpp (implements reusable_if/ISth.h)
reusable_if/
reusable_if/ISth.h   (pure abstract class)
reusable_if/ISthElse.h (pure abstract class)
main.cpp (e.g. instantiates SthThatUsesBothReusableParts and passes to component1/2)

reusable_if /フォルダーがある理由は、component1とcomponent2の両方が同じインターフェースを再利用したいためです(したがって、どちらもインターフェースを排他的に所有していません)。また、プロジェクトは実際に非常に大きく、各フォルダーのクラスに適切な名前空間が必要であると想定しています。

そのようなプロジェクトに名前空間をどのように適用しますか?すべてのクラスを再利用可能/名前空間で宣言するとします::reusable。reusable_ifのインターフェイスを名前空間::reusableまたはに配置する必要があります::reusable_ifか?それとも、component1とcomponent2で使用されているので、何もありませんか?

component1とcomponent2の名前空間はどうですか?覚えておくべきことはありますか?キーワードはusingどうですか?::reusable_ifこの名前空間を追加することにしたとしましょう。名前空間内に配置されている場合、component1とusing reusable_ifcomponent2のヘッダーファイルに入れることはできますか?using ...::component1::component2

上記の例に必ずしも関連しない提案も含めて、私はどんな提案も受け入れます。

4

2 に答える 2

6

個人的な意見の免責事項。あなたの質問は基本的に主観的な答えを求めており、おそらくそれのために閉じられるでしょうが、私はそれに挑戦します。


名前空間は、主に識別子の衝突を回避するために役立ちます。「あなたの」名前空間( )と、mylib::他のすべての人の名前空間(、、、、std::... )があります。これは、名前空間を取得する必要がある範囲です。boost::icu::

識別子の衝突で問題が発生しない限り、プロジェクト(「チームのプロジェクト」など)をサブ名前空間に分割してもメリットはほとんどありません。その場合は、クラスXとを呼び出す戦略を再検討する必要がありますY。;-)

Boostのような巨大なライブラリでは、状況が少し異なります。それらは事実上、別々のチームによって維持されている多くの異なるプロジェクトで構成されているため、プロジェクト固有の識別子がすべてまとめられた場合に互いに衝突するという問題がありますboost::(そして、衝突はカジュアルなテストでは表示されない可能性があります)。

boost::filesystem「サブ名前空間」として見るのをやめ、代わりに個々のプロジェクト、、boost::などの「アイデンティティラッパー」として見ると、プロジェクトがより「ブーストっぽい」ように見えるようになり、画像がより鮮明になります。filesystem::thread::program_options::

于 2013-02-06T09:50:55.113 に答える
4

これが私のプロジェクトに使用するものです。私の主なルールは、各ディレクトリは名前空間であり、各ファイルはクラスですが、例外はほとんどありません(ヘルパー関数を名前空間のサブディレクトリにグループ化することもありますdetailが、別のネストされた名前空間はありません)。

  1. プロジェクト全体を、プロジェクトにちなんで名付けられた単一のトップレベルの名前空間内に保持します。

  2. 各ユーティリティコンポーネントは、最上位の名前空間内に保持しますが、個別のディレクトリに保持します。名前空間をディレクトリツリーとオーバーラップさせないのはこれが唯一の場合です。

  3. プロジェクト内の独立してリリース可能な各コンポーネントを、コンポーネントにちなんで名付けられたネストされた名前空間内に保持します。便宜上、コンポーネントにちなんで名付けられ、名前空間に対応するディレクトリまたはプロジェクトの最上位ディレクトリに直接コンポーネントインターフェイス全体を含む単一のヘッダーを提供します。

  4. ネストされた名前空間内に各コンポーネントの実装を保持しますdetail。クラスとは異なり、名前空間はprivateメンバーの言語をサポートしていませんが、Boostの規則では、名前空間detailはユーザーコードによって直接呼び出されるべきではありません。

project::component::detail::function()または以上のネストproject:::component::class.member()は必要ありません。ADLを容易にする完全なインターフェースを提供する場合、名前の衝突を心配することなく、プロジェクト内のコンポーネント関数を型function(x)の変数として再利用できます。xproject::component::class

ボブおじさんの言葉では、「再利用の単位は解放の単位である」ことに注意してください。各コンポーネントは、一貫性のある相互に依存するクラスと関数の束を提供する必要があります。特に、そのコンポーネントの完全なインターフェイスを提供する必要があります。C ++言語は、引数依存ルックアップ(ADL)を通じてこれをサポートします。HerbSutterによるこの古いコラム「名前空間とインターフェースの原則」を参照してください。

コメントで言及した考慮事項が実際に当てはまらない限り、との両方の存在と存在はコードの臭いである可能性がありreuse_ifます。コンポーネントはリリースの単位である必要があります。コードの一部を個別に再利用できる場合は、それを別のコンポーネントにします。コードが別の部分に依存している場合は、他のコードと一緒にリリースします。これらの依存関係については、Sutterのコラムを参照してください。componentreusable

于 2013-02-06T10:02:10.433 に答える