Oracle® Developer Studio 12.5: C++ ユーザーズガイド

印刷ビューの終了

更新: 2016 年 7 月
 
 

7.3 外部インスタンス

外部インスタンスの場合では、すべてのインスタンスがテンプレートリポジトリ内に置かれます。テンプレートインスタンスは 1 つしか存在できません。つまり、インスタンスが未定義であるとか、重複して定義されているということはありません。テンプレートは必要な場合にのみ再インスタンス化されます。非デバッグコードの場合、すべてのオブジェクトファイル (テンプレートキャッシュに入っているものを含む) の総サイズは、-instances=extern を指定したときの値が -instances=global を指定したときの値より小さくなることがあります。

テンプレートインスタンスは、リポジトリ内では大域リンケージを受け取ります。インスタンスは、現在のコンパイル単位からは、外部リンケージで参照されます。


注 - コンパイルとリンクを別々に実行し、コンパイル処理で -instance=extern を指定する場合は、リンク処理でも -instance=extern を指定する必要があります。

この方法には、別のプログラムに変更したり、プログラムを大幅に変更したりした場合にはキャッシュを常にクリアーする必要があるという欠点があります。キャッシュへのアクセスを一度に 1 回だけに限定しなければならないため、キャッシュは、dmake を使用する場合と同じように、並列コンパイルにおけるボトルネックとなります。また、1 つのディレクトリ内に構築できるプログラムは 1 個だけです。

有効なテンプレートインスタンスがキャッシュ内に存在するかどうかを判断することは、単にインスタンスを本体のオブジェクトファイル内に作成してあとで必要に応じてそれを破棄することよりも時間がかかる可能性があります。

外部リンケージは、–instances=extern オプションによって指定します

インスタンスはテンプレートリポジトリ内に保存されているので、外部インスタンスを使用する C++ オブジェクトをプログラムにリンクするには CC コマンドを使用しなければなりません。

使用するすべてのテンプレートインスタンスを含むライブラリを作成する場合には、-xar オプションでコンパイルしてください。ar コマンドは使用できません。例:

example% CC -xar -instances=extern -o libmain.a a.o b.o c.o

7.3.1 キャッシュの競合の可能性

-instance=extern を指定する場合、キャッシュの競合の可能性があるため、異なるバージョンのコンパイラを同一ディレクトリ内で実行しないでください。-instances=extern テンプレートモデルでコンパイルする場合は、次の点に注意してください。

  • 同一ディレクトリ内に、無関係のバイナリを作成しないでください。同一ディレクトリ内で作成されるすべてのバイナリ (.o.a.so、実行可能プログラム) は関連しているべきです。これは、複数のオブジェクトファイルに共通のすべてのオブジェクト、関数、型の名前は、定義が同一であるためです。

  • dmake を使用する場合などは、複数のコンパイルを同一ディレクトリで同時に実行しても問題はありません。ほかのリンク段階と同時にコンパイルまたはリンク段階を実行すると、問題が発生する場合があります。リンク段階とは、ライブラリまたは実行可能プログラムを作成する処理です。メイクファイル内での依存により、1 つのリンク段階でのコマンドの並列実行は許可されていません。

7.3.2 静的インスタンス


注 - -instances=globalstatic の利点をすべて提供し、かつ欠点がないので、-instances=static オプションは非推奨です。このオプションは、今はもう存在していない問題を克服するために、以前のバージョンで提供されました。

静的インスタンスの場合は、すべてのインスタンスが現在のコンパイル単位内に置かれます。その結果、テンプレートは各再コンパイル作業中に再インスタンス化されます。インスタンスはテンプレートリポジトリに保存されません。

この方法の欠点は、言語の意味解釈が規定どおりでないこと、かなり大きいオブジェクトと実行可能ファイルが作られることです。

インスタンスは静的リンケージを受け取ります。これらのインスタンスは、現在のコンパイル単位以外では認識することも使用することもできません。そのため、テンプレートの同じインスタンス化がいくつかのオブジェクトファイルに存在することがあります。複数のインスタンスによって不必要に大きなプログラムが生成されるので、静的インスタンスのリンケージは、テンプレートが重複してインスタンス化される可能性が低い小さなプログラムだけに適しています。

静的インスタンスは潜在的にコンパイル速度が速いため、修正継続機能を使用したデバッグにも適しています。『dbx コマンドによるデバッグ』を参照してください。


注 - プログラムがコンパイル単位間で、テンプレートクラスまたはテンプレート機能の静的データメンバーなどのテンプレートインスタンスの共有に依存している場合は、静的インスタンス方式は使用しないでください。プログラムが正しく動作しなくなります。

静的インスタンスリンケージは、-instances=static コンパイルオプションで指定します。

7.3.3 大域インスタンス

旧リリースのコンパイラとは異なり、新リリースでは、大域インスタンスの複数のコピーを防ぐ必要はありません。

この方法の利点は、ほかのコンパイラで通常受け入れられる正しくないソースコードを、このモードで受け入れられるようになったという点です。特に、テンプレートインスタンスの中からの静的変数への参照は正当なものではありませんが、通常は受け入れられるものです。

この方法の欠点は、テンプレートインスタンスが複数のファイルにコピーされることから、個々のオブジェクトファイルが通常より大きくなる可能性がある点です。デバッグを目的としてオブジェクトファイルの一部を -g オプションを使ってコンパイルし、ほかのオブジェクトファイルを -g オプションなしでコンパイルした場合、プログラムにリンクされるテンプレートインスタンスが、デバッグバージョンと非デバッグバージョンのどちらであるかを予測することは難しくなります。

テンプレートインスタンスは大域リンケージを受け取ります。これらのインスタンスは、現在のコンパイル単位の外でも認識でき、使用できます。

大域インスタンスは、-instances=global オプションで指定します (デフォルト)。

7.3.4 明示的インスタンス

明示的インスタンスの場合、インスタンスは、明示的にインスタンス化されたテンプレートに対してのみ生成されます。暗黙的なインスタンス化は行われません。インスタンスは現在のコンパイル単位に置かれます。

この方法の利点はテンプレートのコンパイル量もオブジェクトのサイズも、ほかのどの方法より小さくて済むことです。

欠点は、すべてのインスタンス化を手動で行う必要がある点です。

テンプレートインスタンスは大域リンケージを受け取ります。これらのインスタンスは、現在のコンパイル単位の外でも認識でき、使用できます。リンカーは、重複しているものを見つけ、破棄します。

明示的リンケージは、-instances=explicit オプションによって指定します。

7.3.5 半明示的インスタンス

半明示的インスタンスの場合、インスタンスは、明示的にインスタンス化されるテンプレートやテンプレート本体の中で暗黙的にインスタンス化されるテンプレートに対してのみ生成されます。明示的に作成されるインスタンスが必要とするインスタンスは自動的に生成されます。main コード行内で行う暗黙的なインスタンス化は不完全になります。インスタンスは現在のコンパイル単位に置かれます。したがって、テンプレートは再コンパイルごとに再インスタンス化されます。インスタンスが大域リンケージを受けることはなく、テンプレートリポジトリには保存されません。

半明示的インスタンスは、-instances=semiexplicit オプションで指定します。