externテンプレートの使い方 質問する

externテンプレートの使い方 質問する

私は C++0x の N3291 ワーキング ドラフトに目を通していました。そして、extern テンプレートについて興味がありました。セクション 14.7.3 には次のように書かれています。

インライン関数とクラス テンプレートの特殊化を除き、明示的なインスタンス化宣言は、参照先のエンティティの暗黙的なインスタンス化を抑制する効果があります。

参考までに: 「明示的なインスタンス化宣言」という用語は、 の標準的な用語ですextern template。これは、セクション 14.7.2 で定義されています。

extern template std::vector<int>これは、 を使用すると、通常は暗黙的にインスタンス化されるようなことを実行してもインスタンス化std::vector<int>されないということを言っているように聞こえます。

次の段落はさらに興味深いです:

エンティティが同じ翻訳単位内で明示的インスタンス化宣言と明示的インスタンス化定義の両方の対象である場合、定義は宣言の後に続く必要があります。明示的インスタンス化宣言の対象であり、翻訳単位内で暗黙的インスタンス化 (14.7.1) を引き起こすような方法でも使用されるエンティティは、プログラム内のどこかで明示的インスタンス化定義の対象である必要があります。そうでない場合、プログラムは不適切であり、診断は必要ありません。

参考までに: 「明示的なインスタンス化定義」という用語は、次のことを表す標準的な表現です: template std::vector<int>。つまり、 なしですextern

私にとって、これら2つのことはextern template暗黙のインスタンス化を防ぐことを意味しますが、ない明示的なインスタンス化を防止します。つまり、次のようにします。

extern template std::vector<int>;
template std::vector<int>;

2 行目は、1 行目が暗黙的に防止していたことを明示的に実行することで、1 行目を事実上無効にします。

問題は次の通りです。Visual Studio 2008 はこれに同意していないようです。私が使用したい方法は、extern templateユーザーが特定のよく使用されるテンプレートを暗黙的にインスタンス化できないようにし、.cpp ファイルで明示的にインスタンス化してコンパイル時間を短縮できるようにすることです。テンプレートは 1 回だけインスタンス化されます。

問題は、VS2008 では基本的に #ifdef で囲む必要があることです。単一の翻訳単位がexternand 非externバージョンを認識すると、externバージョンが優先され、誰もそれをインスタンス化できなくなります。そして、リンカー エラーが発生します。

私の質問は次のとおりです。

  1. C++0x に従った正しい動作は何ですか?extern template明示的なインスタンス化を防止する必要がありますか?
  2. 前の質問の答えが「そうすべきではない」である場合、VS2008 はエラーです (確かに、仕様よりかなり前に書かれたものなので、VS2008 のせいというわけではありません)。VS2010 はこれをどのように処理しますか? 正しいextern template動作を実装していますか?

ベストアンサー1

それは言う

...クラステンプレートの特殊化を除く

したがって、これは には適用されませんstd::vector<int>が、そのメンバーには適用されます(インライン メンバー関数ではなく、ネストされたクラスでもないメンバー。残念ながら、「クラス テンプレートの特殊化とクラス テンプレートのメンバー クラスの特殊化」の両方を捉える 1 つの用語はありません。そのため、前者だけを使用しながら後者も含めることを意味する箇所があります)。したがって、std::vector<int>とそのネストされたクラス(std::vector<int>::iteratorネストされたクラスとして定義されている など)は、必要に応じて暗黙的にインスタンス化されます。

おすすめ記事