明らかに、テンプレート ライブラリはヘッダーのみである必要がありますが、非テンプレートの場合、いつヘッダーのみにする必要がありますか?
4 に答える
非テンプレート ライブラリがヘッダーのみである可能性があると思われる場合は、とにかくそれを 2 つのファイルに分割し、.h
と の両方を含む 3 つ目のファイルを.cpp
(インクルード ガード付きで) 提供することを検討してください。
そうすれば、あなたのライブラリを多くの異なる TU で使用し、これが多くのコンパイル時間を消費しているのではないかと疑っている人は誰でも、簡単に変更を加えてテストできます。
ユーザーがライブラリをどのように使用するかを選択できることがわかったら、答えはおそらく「できる限りそのオプションを提供する」になります。そのため、複数の TU からそれを含めても、ODR に違反することはほとんどありません。たとえば、static
free ではない関数がstatic
グローバルを参照する場合、運が悪いです。異なる TU のその関数の異なる定義が同じ名前で異なるオブジェクトを参照するためです。これは ODR 違反です。
You could follow Boost.Asio lead.
They simply provide the two versions of the libraries: header-only and header + library.
They do it with a single macro to be defined (or not) before including their headers. I think the default (if not defined) is to use the header-only version.
See Optional Separate Compilation.
Note how they neatly provide a single source file to be compiled that define everything or the option to link against a dynamically loaded library.
テンプレート ライブラリはヘッダーのみである必要はありません。実装には、テンプレート パラメーターとは独立したいくつかの部分が含まれていて、何らかの理由 (コード サイズが少ないなど) で特別なバイナリに分割されている場合があります。
非テンプレート ライブラリが本当にヘッダーのみでなければならないケースは想像できません。ただし、場合によっては、すべてのコードのインライン化を許可することがパフォーマンス上妥当な場合があります。例としては、同期プリミティブ、スレッドローカルストレージ、アトミック操作のプラットフォームおよびコンパイラー固有の実装などのための、プラットフォーム固有のインターフェースのラッパーのライブラリーが挙げられます。
テンプレートがなければ、ヘッダーに実際の定義があります。つまり、2 つのファイルにヘッダーが含まれている場合、複数の定義が取得され、コードがコンパイルされません。
つまり、ヘッダーに定義を入れることは非常に悪い考えです。宣言のみとテンプレートに固執する必要があります。
テンプレートに関しては、コンパイラは、同じヘッダーを複数回含める可能性があることを認識しており、同じコードを何度も生成することはありません。
編集:「すべてをインラインに保つ」という意味であれば、これは非常に悪いアプローチだと思います。ヘッダー ファイルは完全に読み取れなくなり、実装を変更すると、ライブラリのユーザーはすべてを再コンパイルする必要があります。