コンパイラは、複数の .cpp ファイルで定義された非テンプレート クラスについて不平を言うのに、(クラスの .inl ファイルを含めることによって) さまざまな .cpp ファイル間で定義が重複しているテンプレート クラスには問題がないのはなぜですか。クラスは複数の .cpp ファイルでも明示的にインスタンス化されていますか?
3 に答える
非テンプレートのケースは、そのシナリオではプログラムが 1 つの定義ルールに違反しているため、リンカー (コンパイラーではない) が複数の定義について文句を言うためです。
一方、テンプレートの場合、言語はこれが機能する必要があることを指定し、リンカーは何をすべきかを整理します。ただし、明示的なテンプレートのインスタンス化を非テンプレート関数と同じように扱う必要があるかどうかは 100% わかりません。
すべてのコンパイラは常に文句を言いますか? そうしたものを見たことがなく、標準ではそれが許可されていません。すべての定義が同一である限り、クラスまたはテンプレートを各翻訳単位で 1 回定義することが許可されています。実際、完全な型である必要がある方法でクラスを使用するすべての翻訳単位でクラスを定義する必要があります。C++ には、クラス定義を他の翻訳単位にエクスポートするメカニズムがありません。
クラスと関数を混同していませんか?インラインでない限り、関数を複数回定義することはできません。関数テンプレートを使用する各翻訳単位で関数テンプレートを定義する必要があります。関数テンプレートには、クラスおよびクラス テンプレートと同じ規則が適用されます。
複数の翻訳単位で関数を定義することによって、またはクラスまたはテンプレートの定義が (前処理後、および名前バインディングを含めて) トークンごとに同一ではないことによって、これらの規則に違反すると、未定義の動作が発生することに注意してください。コンパイラ (実際にはリンカ) はそれについて不平を言うかもしれませんが、必須ではありません: ほとんどは関数の複数の定義について不平を言いますが、クラスまたはテンプレートの定義が翻訳単位間で異なる場合に不平を言うものは知りません。
テンプレート関数はインラインであり、インライン関数は、各定義が同一である限り、複数のコンパイル ユニットで定義できます。