24

私は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バージョンが勝ち、誰もそれをインスタンス化しないためです。そして、リンカーエラーが発生します。

だから、私の質問は次のとおりです。

  1. C ++ 0xによる正しい動作は何ですか?extern template明示的なインスタンス化を防ぐ必要がありますか?
  2. 前の質問に対する答えがそうではないということである場合、VS2008はエラーです(当然のことながら、仕様よりもかなり前に記述されているため、彼らのせいではありません)。VS2010はこれをどのように処理しますか?正しいextern template動作を実装していますか?
4

1 に答える 1

7

それは言う

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

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

于 2011-07-29T13:11:38.863 に答える