20

テンプレートの明示的なインスタンス化について読んでいます:

template struct MyStruct<long>;

「かなり珍しい」と表現されていたのですが、どのような状況で役立つのでしょうか?

4

4 に答える 4

15

ユースケースの1つは、エンドユーザーから定義を非表示にすることです。

tpl.h

template<typename T>
void func(); // Declaration

tpl.cpp

template<typename T>
void func()
{
    // Definition
}

template void func<int>(); // explicit instantiation for int
template void func<double>();  // explicit instantiation for double

main.cpp

#include "tpl.h"
int main()
{
    func<double>(); // OK
    func<int>(); // OK
    // func<char>(); - Linking ERROR
}
于 2012-10-25T13:10:20.830 に答える
9

明示的なインスタンス化は、テンプレートライブラリの使用を最適化するように設計されており、ソースコード形式ではなくコンパイル済みのバイナリ形式で(主に使用される)テンプレートインスタンスの一部を提供します。これにより、エンドユーザーアプリケーションのコンパイルとリンクの時間が短縮されます。たとえばstd::basic_string<char>std::basic_string<wchar_t>STLディストリビューションで明示的にインスタンス化できるため、各翻訳ユニットでのインスタンス化の作業を回避できます。

明示的なインスタンス化は、テンプレートの実装をカプセル化し、このテンプレートを既知のタイプのセットでのみ使用する場合にも役立ちます。この場合、テンプレート関数(freeまたはmembers)の宣言のみをヘッダーファイル(.h/.hpp)に配置し、それらを変換単位(.cpp)で定義できます。

例:

 // numeric_vector.h
 //////////////////////////////////////////////////
 template <typename T> class numeric_vector
 {
    ...
    void sort();
 };


 // numeric_vector.cpp
 //////////////////////////////////////////////////
 // We know that it shall be used with doubles and ints only,
 // so we explicitly instantiate it for doubles and ints
 template class numeric_vector<int>;
 template class numeric_vector<double>;

 // Note that you could instantiate only specific
 // members you need (functions and static data), not entire class:
 template void numeric_vector<float>::sort();

 template <typename T> void numeric_vector<T>::sort()
 {
   // Implementation
   ...
 }

また、明示的なインスタンス化は、テンプレートからインスタンス化された型が必要な場合に役立ちますが、インスタンス化自体をトリガーしない構文構造内、たとえばVisualStudioのようなコンパイラ固有のメタ機能など__declspec(uuid)です

実装のカプセル化に使用できる別の手法(明示的な特殊化)との違いに注意してください。明示的な特殊化では、特殊化するタイプごとに特定の定義を提供する必要があります。明示的なインスタンス化を使用すると、単一のテンプレート定義が得られます。

明示的な特殊化を使用した同じ例を考えてみましょう。

例:

 // numeric_vector.h
 //////////////////////////////////////////////////
 template <typename T> class numeric_vector
 {
    ...
    void sort();
 };

 template <> class numeric_vector<int>
 {
    ...
    void sort();
 };

 template <> class numeric_vector<double>
 {
    ...
    void sort();
 };

 // Specializing separate members is also allowed
 template <> void numeric_vector<float>::sort();

 // numeric_vector.cpp    
 //////////////////////////////////////////////////
 void numeric_vector<int>::sort()
 {
   // Implementation for int
   ...
 }

 void numeric_vector<double>::sort()
 {
   // Implementation for double
   ...
 }

 void numeric_vector<float>::sort()
 {
   // Implementation for float       
   ...
 }
于 2012-10-25T15:34:17.053 に答える
5

明示的な特殊化により、実装を非表示にすることができますが、これは、ご存知のように、テンプレートでは通常不可能です。

この手法は、ジオメトリを処理するライブラリで一度だけ見たことがあり、独自のベクトル クラスを提供していました。

だからあなたは使うことができます

lib::Vector<MyShape>

提供されたいくつかの基本的な機能lib::Vectorと基本的な実装を使用し、それらのクラス (すべてではなく一部) で使用した場合

lib::Vector<lib::Polygon>

明示的な特殊化を使用します。実装にアクセスすることはできませんが、裏でハードコアな最適化が行われているに違いありません。

于 2012-10-25T12:59:12.153 に答える
0

ヘッダー ファイルでテンプレート関数を定義したくない場合は、別のソース ファイルで関数を定義し、明示的なテンプレートのインスタンス化を使用して、使用するすべてのバージョンをインスタンス化できます。次に、完全な定義ではなく、ヘッダー ファイルに前方宣言のみが必要です。

于 2012-10-25T12:59:15.443 に答える