5

次のようなテンプレートクラスがあります。

template<class T> class C
{
    void A();
    void B();

    // Other stuff
};

template<class T> void C<T>::A() { /* something */ }
template<class T> void C<T>::B() { /* something */ }

私が欲しいのはA、のデフォルトBと「その他のもの」を保持しながらのみ、明示的な特殊化を提供することです。

私がこれまでに試したことは

class D { };
template<> void C<D>::A() { /*...*/ } // Gives a link error: multiple definition

私が試みた他のすべてのバリアントは、解析エラーで失敗します。


私がしたこと:

元々の問題は、明示的な特殊化がヘッダーファイルに含まれていたため、複数のオブジェクトファイルにダンプされ、リンクが混乱していたことでした(リンカーは、シンボルのすべてのインスタンスが同じであることに気付かないのはなぜですか?)

解決策は、明示的な特殊化をヘッダーファイルからコードファイルに移動することです。ただし、ヘッダーファイルの他のユーザーをデフォルトバージョンにインスタンス化しないようにするには、プロトタイプをヘッダーに戻す必要がありました。次に、GCCに明示的な特殊化を実際に生成させるために、正しいタイプのダミー変数をコードファイルに配置する必要がありました。

4

2 に答える 2

8

Martin Yorkのインラインソリューションの代わりに、ヘッダーファイルで行うこともできます。

class D { };
template<> void C<D>::A(); // Don't implement here!

そして、実装とともに.cppファイルを提供します。

template<> void C<D>::A() { /* do code here */ }

したがって、単一の定義を提供することにより、複数の定義を回避します。これは、ライブラリを公開するときに、特定のタイプの実装をテンプレートヘッダーファイルから隠すのにも役立ちます。

于 2009-09-26T18:13:39.077 に答える
5

試す

template<> inline void c<int>::A() { ... }
//         ^^^^^^

ヘッダーファイルで定義したとおりです。それを見る各ソースファイルは、その明示的なバージョンを構築します。これにより、リンクエラーが発生します。したがって、jsutはそれをインラインとして宣言します。

于 2009-09-26T17:25:34.497 に答える