私は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行目は、最初の行が暗黙的に発生するのを防いだことを明示的に実行することにより、最初の行を効果的に無効にします。
問題はこれです:VisualStudio2008は同意していないようです。私が使用したい方法extern template
は、ユーザーが特定の一般的に使用されるテンプレートを暗黙的にインスタンス化しないようにすることです。これにより、.cppファイルで明示的にインスタンス化して、コンパイル時間を短縮できます。テンプレートは一度だけインスタンス化されます。
問題は、VS2008では基本的にそれらの周りに#ifdefを設定する必要があることです。単一の翻訳ユニットがバージョンextern
と非extern
バージョンを認識した場合、extern
バージョンが勝ち、誰もそれをインスタンス化しないためです。そして、リンカーエラーが発生します。
だから、私の質問は次のとおりです。
- C ++ 0xによる正しい動作は何ですか?
extern template
明示的なインスタンス化を防ぐ必要がありますか? - 前の質問に対する答えがそうではないということである場合、VS2008はエラーです(当然のことながら、仕様よりもかなり前に記述されているため、彼らのせいではありません)。VS2010はこれをどのように処理しますか?正しい
extern template
動作を実装していますか?