これに対処する正しい方法は、名前の競合が発生しにくくなるようにビルド環境をセットアップすることです。
ライブラリ作成のガイドライン
たとえば、ほとんどのサードパーティ ライブラリは、プレーン ファイルをコンパイラのインクルード パスに導入しません。代わりに、ファイルを含むディレクトリを導入します。さまざまなモジュールにサブディレクトリを導入することで、柔軟性を高めることができます。
Boostのディレクトリ構造を考えてみましょう。トップレベルでは、Boost はインクルード検索パスに 1 つの名前のみを導入します:boost
ディレクトリ。boost
そうすれば、衝突する可能性が高い多くのヘッダー ファイル名 ( array.hpp
、thread.hpp
、または など) が導入されていてもfunction.hpp
、それらはすべてサブディレクトリにラップされます。
#include <boost/thread.hpp> // this is boost's header
#include "thread.hpp" // some header specific to my current project
// no name clash :)
Boost に同梱されているさまざまなライブラリにも同じ概念が使用されています。たとえば、Boost lockfree と Boost assign の両方にqueue.hpp
ヘッダーがあります。しかし、それらは異なるサブディレクトリにあるため、衝突はありません:
#include <boost/lockfree/queue.hpp>
#include <boost/assign/std/queue.hpp> // no clash :)
適切なヘッダー ファイルを簡単に見つけられるようにするために、Boost はインクルード ファイルと名前空間に同じ構造を使用します。ロックフリー キューはboost::lockfree
名前空間に存在し、割り当てキュー ヘッダーの関数は に移動しboost::assign
ます。そうすれば、一致する名前空間をインクルード ファイルから簡単に見つけられるだけでなく、名前空間の衝突の可能性も減少します。これは、名前空間の衝突がファイル レイヤーでの物理名の衝突として現れる可能性があるためです。
これらのガイドラインを独自のプロジェクトに適応させることができます
- そのままのインクルード ファイルをインクルード パスに直接導入しないでください。代わりに、インクルード パスが名前で汚染されないように、それらをディレクトリにグループ化します。
- ディレクトリ ツリーを使用して、単一のライブラリ内のモジュールのインクルード ファイルをさらに構造化します。
- 物理構造と論理構造を一致させてください。ファイルシステムのインクルード パスは、可能であれば名前空間の階層に似ている必要があります。
これにより、そもそもほとんどの名前衝突が回避されます。問題は、これらのルールに従わないサードパーティのライブラリを使用する必要があり、制御できない衝突が発生した場合はどうなるかということです。
サードパーティ ライブラリによる名前の衝突に対処するためのガイドライン
答えは残忍であり、ビルド環境を通じて分離を強制することです。競合するライブラリを一意に識別可能なサブディレクトリに移動してインクルード パスを再編成し、物理的な競合を解決します。これは通常、重要ではありません。論理的な競合が発生すると、パッチを適用して再コンパイルする必要があり、これはさらに不便です。しかし、ここで実際に名前の競合が発生した場合は、ライブラリ ベンダーの少なくとも 1 つがうまく機能していないことを示しており、バグを報告することを検討する必要があります。
物理的な衝突を修正するようなアドホックな修正#include_next
や、論理的な衝突を修正するためのプリプロセッサの定義には近づかないでください。それらは汚いハックであり、一時的に問題を解決するかもしれませんが、最終的に戻ってきて噛む可能性が非常に高くなります.