プログラムでテンプレートと静的オブジェクトを使用していると、-instances=extern を指定してコンパイルした場合に未定義シンボルのリンク時エラーが発生します。これは、デフォルト設定の -instances=global では問題になりません。コンパイラは、大域的でない名前空間スコープのオブジェクトに対するテンプレートからの参照をサポートしません。次の例を考えてみましょう。
static int k; template<class T> class C { T foo(T t) { ... k ... } }; |
この例では、テンプレートクラスのメンバーは静的な名前空間スコープ変数を参照します。名前空間スコープはファイルスコープを含むことに注意してください。コンパイラは、静的な名前空間スコープ変数を参照するテンプレートクラスのメンバーをサポートしません。複数のコンパイル単位からテンプレートがインスタンス化されると、各インスタンスは異なる k を参照します。つまり、C++ 単一定義規則違反が発生し、コードは定義されていない動作を起こします。
ユーザーは、k をどのように使用するか、それによってどのような効果を得ようとするかに基づき、次に示す代替方法を実施できます。2 番目のオプションは、クラスのメンバーの関数テンプレートにのみ使用できます。
変数に外部リンケージを持たせる
int k; // not static |
すべてのインスタンスは、k の同じコピーを使用します。
変数をクラスの静的メンバーにする
template<class T> class C { static int k; T foo(T t) { ... k ... } }; |
静的なクラスメンバーは外部リンケージを持ちます。C<T>::foo のインスタンスが使用する k はそれぞれ異なります。C<T>::k のインスタンスは、ほかの関数で共有することができます。通常はこのオプションが使用されます。